Effiziente wissenschaftliche Notation

12

Neulich erklärte mir mein Chemielehrer die wissenschaftliche Notation (indem er eine kleine Zahl verwendete und sie mit Zehnerpotenzen multiplizierte, um große Zahlen leichter auszudrücken), was mich ein paar Jahre zurückbrachte, als ich sie zum ersten Mal lernte. Nachdem wir die Grundlagen erlernt hatten, hatten wir einige typische mathematische Fragen gestellt, von denen einige wie folgt lauteten:

Stellen Sie in der wissenschaftlichen Schreibweise Folgendes dar:
a) 50000000
b) 120000000000000
c) 900000000000000000000000000000000000
d) pi ^ e ^ i ^ j ^ k ^ std :: vector
...
z) 200
...

Und ich dachte: "Was? Uns wurde gesagt, dass die wissenschaftliche Notation verwendet wurde, um das Schreiben großer Zahlen effizienter zu machen, aber einige Fälle sind überhaupt nicht effizienter!"

Betrachten Sie die Nummer

300

und seine Darstellung in wissenschaftlicher Notation:

3x10^2

Was, die wissenschaftlich notierte Version nimmt tatsächlich mehr Platz ein? Das können wir jetzt nicht haben, oder? (Der Platz auf dem Bildschirm ist kostbar.)
Wir könnten selbst bestimmen, ob es platzsparender ist, eine Zahl in wissenschaftlicher Notation zu schreiben oder nicht, oder ...

Aufgabe

Ihr Programm oder Ihre Funktion sollte eine einzelne positive Zahl nbeliebiger Größe (bis zu der von Ihrer Sprache unterstützten Größe) als Eingabe verwenden und die wissenschaftlich notierte Version der Zahl ausgeben.
Wenn die ursprüngliche Nummer nnach dem Entfernen der nachgestellten Nullen und der nachgestellten Dezimalstelle weniger oder weniger Zeichen als die wissenschaftlich notierte Version enthält, müssen Sie nstattdessen diese ursprüngliche Nummer ausgeben .

Ihr Code muss so kurz wie möglich sein, da die Ausgabe auch so kurz wie möglich sein muss.

Spezifikationen

Efficient Scientific Notation ist wie folgt definiert:

bx10^e

bist die Eingangszahl, die durch Zehnerpotenzen geteilt wird, so dass 1 <= b < 10. Bei dieser Zahl müssen alle nachgestellten Nullen (und gegebenenfalls der Dezimalpunkt) entfernt werden. Sie muss jedoch die Genauigkeit der ursprünglichen Zahl aufweisen (natürlich bis zum Dezimalpunkt in Ihrer Sprache). Dh 90000wird 9, 13.500wird 1.35, 0.000675wird 6.75usw. Wenn diese Zahl mehr Dezimalstellen enthält, als Ihre Sprache verarbeiten kann, sollte sie auf diese maximale Anzahl von Dezimalstellen gerundet werden.

eist der Exponent, auf den zehn erhöht werden n = b x 10^e(denken Sie daran, dass diese Zahl negativ sein muss, wenn sie nkleiner als 1 ist). Diese Zahl sollte keine nachgestellten Nullen oder Dezimalstellen enthalten (hauptsächlich, weil etwas nicht stimmt, wenn es sich nicht um eine Ganzzahl handelt ...).

Die Zeichen x10^ müssen so bleiben, wie sie in der Zeichenfolge zwischen bund stehen e.

Testfälle

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

Wertung

Das ist , also gewinnt der kürzeste Code in Bytes.

Andere Regeln und Erläuterungen

  • Nachgestellte Nullen (und / oder Nachkommastellen) werden nicht auf die Anzahl der Zeichen der ursprünglichen Eingabenummer angerechnet n. Beachten Sie dies in Fällen wie Testfall 6
  • Sie können davon ausgehen, dass die eingegebene Zahl, wenn sie kleiner als 1 ist, immer mit einer 0 für die Einerstelle beginnt (wie in den Testfällen 5-8).
  • Die eingegebene Nummer wird niemals negativ sein
  • Eingebaute Elemente, die diese Herausforderung zu trivialen und standardmäßigen Schlupflöchern machen, sind nicht zulässig
  • Eine nachfolgende Zeile in der Ausgabe ist OK

EDIT
Dank user81655 für den Hinweis auf Testfälle 7 und 8 hatten falsche Zehnerpotenzen. Ich habe diese jetzt behoben, also stellen Sie sicher, dass Ihr Code sie korrekt auswertet.

MC ΔT
quelle
7
Also, sollte ich fragen, was die Ausgabe für die Eingabe pi^e^i^j^k^std::vectorwäre?
Geobits
@Geobits Hmm, na ja, wenn Sie std :: vector einen numerischen Wert zuweisen können, dann vielleicht ... Nein, in der Eingabe sind nur Zahlen vorhanden (mit Ausnahme einer Dezimalstelle für die Gleitkomma-Eingabe).
MC ΔT
Dies wäre weitaus einfacher und wir würden weniger von Ihrem "kostbaren Bildschirm" e9000 -> 9e3
beanspruchen,
1
@Cyoce Ich habe darüber nachgedacht, aber ich habe diese Herausforderung wirklich auf die Art und Weise gegründet, in der sie allgemein geschrieben ist (wie in physischer Form), was so zu sein scheint x10^. Und es wäre ein gutes Stück Überarbeitung der Frage, die ich jetzt, wo sie veröffentlicht ist, nicht für angemessen halte
MC ΔT
1
@ghosts_in_the_code Das war sie nicht, daher "brachte mich ein paar Jahre zurück zu dem Zeitpunkt, als ich es [im Matheunterricht] zum ersten Mal lernte"
MC ΔT

Antworten:

4

ES6, 83 81 Bytes

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

Scheitert wahrscheinlich in einigen Randfällen, in denen das toStringExponentialformat erforderlich ist.

Bearbeiten: 2 Bytes dank @ user81655 gespeichert.

Neil
quelle
Gute Idee. Übrigens, es sieht so aus, als hättest du das /am Ende des regulären Ausdrucks vergessen .
user81655
Sie können dies auch leicht neu anordnen, um 2 Bytes zu sparen:x=>(e=s=>s.replace(/e\+?/,'x10^'),z=e(x.toExponential()),y=e(''+x))[z.length]?z:y
user81655
@ user81655 Ah, was da passiert ist, ist, dass mein Browser mich verwirrt hat, als ich die lange Zeile so umbrochen habe, dass ich dachte, eine neue Zeile wäre versehentlich hineingeschlichen.
Neil
2

Python 3, 346 342 319 302 Bytes

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))

Wahrscheinlich furchtbar golfen, aber hey, das ist mein erster Versuch mit so etwas. Es ist schwer zu lesen, also muss es gut sein.

Soweit mir bekannt ist, sollte es auf jeden Fall funktionieren, auch wenn Python die Tendenz hat, Zahlen über jeden Schwellenwert hinaus automatisch in wissenschaftliche Notation umzuwandeln (außer mit diesem coolen und ausgefallenen 'e'). Ich erinnere mich nicht genau, wie ich dafür gesorgt habe, dass Standardformularnummern zurückgegeben werden können, aber das tut es.

Reecer6
quelle
2

Perl 6, 96-90 Bytes

Ich habe das Gefühl, dass dies kürzer sein könnte, aber dies ist mein Bestes für den Moment

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

Verwendung : Weisen Sie dies einer Variablen zu

Hier ist es ein bisschen ungolfed mit ein paar schlechten Kommentaren:

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.
}
Hotkeys
quelle
Tauschen Sie $_ <1mit 1>$_und 1 <=* <10mit10>*>=1
Brad Gilbert b2gills
Eigentlich wollte ich das letzte Nacht machen, aber ich habe es vergessen. Ich werde es aktualisieren, wenn ich nach Hause
komme
2

TI BASIC (nspire): 112 Byte

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

Erläuterung

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

Konvertiert die Eingabe mit der Formatfunktion in wissenschaftliche Notation, wenn sie bereits nicht in diesem Format vorliegt, da kleine Dezimalstellen automatisch konvertiert werden.

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

Findet die Position des ausgefallenen E, das Exponenten bezeichnet, und ersetzt sie durch "x10 ^".

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

Prüft, welche Ausgabe größer ist und gibt die optimale zurück. Es sei denn, es handelt sich um eine kleine Dezimalstelle, die standardmäßig kleiner ist.

Pavel
quelle
0

Python (3.5) 177 Bytes

Eine Lösung mit regulären Ausdrücken

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

Erläuterung

Import des Regexp-Moduls

import re

Definition der zu ersetzenden Lambda-Funktion edurchx10^

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

Konvertierung des Strings in wissenschaftliche Notation

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

Entfernen Sie die 0-Füllung in der Originalzeichenfolge

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

Länge vergleichen

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

Ergebnisse

>>> [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
quelle