Efektywna notacja naukowa

12

Któregoś dnia mój nauczyciel chemii wyjaśniał nam notację naukową (używając małej liczby i mnożąc ją przez potęgę dziesięciu, aby łatwiej wyrażać duże liczby), co przywróciło mnie o kilka lat, kiedy się go nauczyłem. Po zapoznaniu się z podstawami zadaliśmy kilka typowych pytań matematycznych, z których niektóre były następujące:

W notacji naukowej reprezentuj:
a)
50000000 b) 120000000000000
c) 90000000000000000000000000000000000000
d) pi ^ e ^ i ^ j ^ k ^ std :: vector
...
z) 200
...

I pomyślałem: „Co? Powiedziano nam, że notacja naukowa została użyta, aby zwiększyć efektywność pisania dużych liczb, ale niektóre przypadki wcale nie są bardziej efektywne!”

Rozważ numer

300

i jego reprezentacja w notacji naukowej:

3x10^2

Co, naukowo zanotowana wersja faktycznie zajmuje więcej miejsca? Nie możemy tego teraz mieć, prawda? (Przestrzeń na ekranie jest cenna.)
Moglibyśmy sami ustalić, czy bardziej efektywne jest miejsce na zapisanie liczby w notacji naukowej, czy nie, lub ...

Zadanie

Twój program lub funkcja powinna przyjąć jako wartość wejściową pojedynczą liczbę dodatnią no dowolnym rozmiarze (do poziomu obsługiwanego przez Twój język) i wygenerować zanotowaną naukowo wersję liczby.
Jeśli jednak oryginalny numer n, po usunięciu końcowych zer i końcowego miejsca po przecinku, zajmuje mniej lub tyle samo znaków do wyświetlenia niż jego notowana naukowo wersja, należy nzamiast tego wydrukować ten oryginalny numer .

Twój kod musi być jak najkrótszy, ponieważ dane wyjściowe również muszą być tak krótkie, jak to możliwe.

Dane techniczne

Efektywna notacja naukowa jest zdefiniowana następująco:

bx10^e

bjest liczbą wejściową odpowiednio podzieloną przez potęgi 10, takie jak 1 <= b < 10. Ta liczba musi mieć wszystkie zera końcowe (i kropkę dziesiętną, jeśli jest wymagana), ale musi mieć dokładność oryginalnej liczby (do limitu dziesiętnego w twoim języku, oczywiście). Oznacza to, że 90000staje się 9, 13.500staje się 1.35, 0.000675staje się 6.75itd. Jeśli liczba ta zawiera więcej miejsc po przecinku, niż twój język może znieść, należy ją zaokrąglić do maksymalnej liczby miejsc po przecinku.

ejest wykładnikiem potęgi, do którego podniesiono dziesięć, że n = b x 10^e(pamiętaj, że liczba ta musi być ujemna, jeśli njest mniejsza niż 1). Liczba ta nie powinna mieć żadnych zer końcowych ani miejsca dziesiętnego (głównie dlatego, że jeśli nie jest liczbą całkowitą, coś jest nie tak ...).

Znaki x10^ muszą pozostać takie, jak w ciągu między bi e.

Przypadki testowe

Input -> output
1 -> 1
20 -> 20
3000000 -> 3x10^6
400000 -> 400000
0.008093 -> 0.008093
0.007835000000000 -> 0.007835
0.000003000000 -> 3x10^-6
0.00000065 -> 6.5x10^-7
0 -> 0

Punktacja

To jest , więc wygrywa najkrótszy kod w bajtach.

Inne zasady i wyjaśnienia

  • Zera końcowe (i / lub końcowe miejsce dziesiętne) nie są liczone do liczby znaków oryginalnej liczby wejściowej n. Pamiętaj o tym w przypadkach takich jak przypadek testowy 6
  • Możesz założyć, że jeśli liczba wejściowa jest mniejsza niż 1, zawsze będzie zaczynać się od 0 dla cyfry jedynek (jak w przypadkach testowych 5-8).
  • Numer wejściowy nigdy nie będzie ujemny
  • Wbudowane rozwiązania, które sprawiają, że wyzwanie jest trywialne, a standardowe luki są niedozwolone
  • Końcowy znak nowej linii w wynikach jest OK

EDYCJA
Dzięki użytkownikowi 81655 za wskazanie przypadków testowych 7 i 8 miał niepoprawne moce dziesięciu. Naprawiłem je, więc upewnij się, że Twój kod ocenia je poprawnie.

MC ΔT
źródło
7
Czy powinienem zapytać, jaki pi^e^i^j^k^std::vectorbyłby wynik dla danych wejściowych ?
Geobits
@Geobits Hmm, cóż, jeśli możesz przypisać wartość liczbową do std :: vector, to może ... Nie, tylko liczby będą obecne na wejściu (z wyjątkiem miejsca dziesiętnego dla wprowadzania zmiennoprzecinkowego).
MC ΔT
Byłoby to o wiele łatwiejsze ie9000 -> 9e3
zajęlibyśmy
1
@Cyoce Myślałem o tym, ale tak naprawdę oparłem to wyzwanie na sposobie, w jaki jest ogólnie napisany (jak w fizycznym piśmie), co wydaje się być x10^. Byłoby to sporo przeróbek na pytanie, które nie wydaje mi się właściwe teraz, gdy zostało opublikowane
MC ΔT
1
@ghosts_in_the_code Nie była, dlatego „przyniosło mi kilka lat wstecz, kiedy po raz pierwszy nauczyłem się tego [na zajęciach z matematyki]”
MC ΔT

Odpowiedzi:

4

ES6, 83 81 bajtów

x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y

Prawdopodobnie zawiedzie w niektórych przypadkach krawędzi, w których toStringnalega na format wykładniczy.

Edycja: Zapisano 2 bajty dzięki @ user81655.

Neil
źródło
Dobry pomysł. Nawiasem mówiąc, wygląda na to, że zapomniałeś /o końcu wyrażenia regularnego.
user81655
Możesz także zmienić to nieco, aby zaoszczędzić 2 bajty:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655
@ user81655 Ach, tak się stało, że moja przeglądarka pomyliła mnie, owijając długą linię w taki sposób, że myślałem, że przez pomyłkę wkradła się nowa linia.
Neil
2

Python 3, 346 342 319 302 bajtów

L=len;N=str(float(input()))
if N.endswith('.0'):N=N[:-2]
if'e'in N:C,P=N.split('e');N=N.replace('e','x10^')
else:
 C=N.strip('.0').replace('.','');F=N.find('.')
 if L(C)>1:C=C[0]+'.'+C[1:]
 P=((L(N) if F==-1 else F)-1-N.lstrip('0').find(C[0]))
print(min([N,'{0}x10^{1}'.format(C,int(P))],key=L))

Prawdopodobnie strasznie grał w golfa, ale hej, to moja pierwsza próba czegoś takiego. Trudno ją przeczytać, więc musi być dobra.

O ile mi wiadomo, powinno działać w każdym przypadku, nawet przy tendencji Pythona do automatycznego przekształcania liczb przekraczających dowolny próg w notację naukową (z wyjątkiem tego fajnego i fantazyjnego „e”). Nie pamiętam dokładnie, w jaki sposób udało mi się zwrócić standardowe numery formularzy, ale robi to.

Reecer6
źródło
2

Perl 6, 96 90 bajtów

Wydaje mi się, że może to być krótsze, ale na razie jest to moje najlepsze

{my \s=($_,*×(1>$_??10!!.1)…10>*>=1);min(s[*-1]~"x10^"~(1>$_??1-s!!s-1),$_,by=>&chars)}

użycie : przypisz to do zmiennej

Tutaj jest trochę niepoprawny z jakimś złym komentarzem:

my &f = -> $n {
    my $a = 1 > $n ?? 10 !! .1;             # If $n < 1, we will multiply by 10
                                            # in the sequence below, else by 0.1

    my @seq = ($n, * × $a ... 10 > * >= 1); # Sequence starting at $n, 
                                            # multiply the previous value by $a
                                            # until we reach a number 1 <= x < 10

    # Join the last element in @seq, "x10^", and the length of @seq,
    # with an extra subtraction for numbers less than 1.
    # this gets us our scientific notation.
    my $science = @seq[*-1] ~ "x10^" ~ @seq - (1 > $n ?? @seq*2 !! 1); 

    min($science, $n, by => &chars) # Uses the &chars function to
                                    # choose a min value and return it.
}
Skróty klawiszowe
źródło
Zamień $_ <1z 1>$_lub 1 <=* <10z10>*>=1
Brad Gilbert b2gills
Naprawdę chciałem to zrobić zeszłej nocy, ale zapomniałem. Zaktualizuję go, kiedy wrócę do domu
Hotkeys,
2

TI BASIC (nspire): 112 bajtów

Define f(x)=
Prgm
string(x)➝a
If x≥1 Then
format(x,"s")➝a
EndIf
instring(a,"ᴇ")➝b
left(a,b-1)&"x10^"&mid(a,b+1)➝a
If dim(a)<dim(string(n)) or x<1 Then
Disp a
Else
Disp x
Endif
EndPrgm

Wyjaśnienie

If x≥1 Then
format(x,"s")➝a
EndIf

Konwertuje dane wejściowe na notację naukową za pomocą funkcji formatu, jeśli nie jest już w tym formacie - ponieważ małe dziesiętne są automatycznie konwertowane.

instring(a,"ᴇ")➝b
left(a,b-1)&"x10^"&mid(a,b+1)➝a

Znajduje pozycję fantazyjnego E, który oznacza wykładniki potęgowe i zastępuje go „x10 ^”.

If dim(a)<dim(string(x)) or x<1 Then
Disp a
Else
Disp x
Endif

Sprawdza, która moc wyjściowa jest większa i zwraca optymalną. Chyba że jest to mały ułamek dziesiętny, który jest domyślnie mniejszy.

Pavel
źródło
0

Python (3.5) 177 bajtów

Rozwiązanie wykorzystujące wyrażenie regularne

import re
g=lambda s:re.sub(r"e\+?(-?)0?","x10^\\1",s)
def f(i):
 t=g(re.sub(r"\.[0]*e","e","%e"%i))
 u=g(re.sub(r"(\..*)[0]*$","\\1",str(i)))
 return t if len(u)>len(t) else u

Wyjaśnienie

Import modułu regexp

import re

Definicja funkcji lambda do zastąpienia eprzezx10^

g=lambda s:re.sub("e\+?(-?)0?","x10^\\1",s)
def f(i):

Konwersja ciągu w notacji naukowej

 t=g(re.sub(r"\.[0]*e","e","%e"%i))

Usuń 0 wypełnień w oryginalnym sznurku

 u=g(re.sub(r"(\..*)[0]*$","\\1",str(i)))

porównaj długość

 return t if len(u)>len(t) else u

Wyniki

>>> [f(i) for i in [1, 20, 3000000, 400000, 0.008093, 0.007835000000000, 0.000003000000, 0.00000065, 0]]
['1', '20', '3x10^6', '400000', '0.008093', '0.007835', '3x10^-6', '6.5x10^-7', '0']
Erwan
źródło