Wenn Sie einen Bruch in eine Dezimalzahl umwandeln und diese Zahl speichern möchten, müssen Sie sie häufig runden, da Sie nur eine bestimmte Menge an Speicher verwenden möchten. Angenommen, Sie können nur 5 Dezimalstellen speichern, dann wird 5/3 zu 1,6667. Wenn Sie nur 2 Dezimalstellen speichern können, beträgt diese 1,7 (jetzt wird angenommen, dass sie immer zwischen 0 und 9,99 liegt ...).
Wenn Sie nun versuchen, diesen Prozess mit 1.7 umzukehren und Ihren Bruch wieder herzustellen, kann dies schwierig sein, da Sie wissen, dass 1.7 nur eine gerundete Zahl ist. Natürlich können Sie 17/10 probieren, aber das ist eher ein "hässlicher" Bruchteil im Vergleich zum "eleganten" 5/3.
Das Ziel ist es nun, den Bruch a / b mit dem kleinsten Nenner b zu finden, der bei richtiger Rundung die gerundete Dezimalzahl ergibt.
Einzelheiten
Die Eingabe enthält eine Zeichenfolge mit einer Zahl von 1 bis 5 Ziffern, die zwischen 0 (einschließlich) und 10 (nicht einschließlich) mit einem '.' nach der ersten Ziffer. Angenommen, n
die Anzahl der Stellen. Die Ausgabe muss eine Liste / ein Array mit zwei Ganzzahlen [numerator, denominator]
oder ein rationaler Datentyp sein (Sie können einen eigenen Datentyp erstellen oder einen integrierten Datentyp verwenden), bei dem der Zähler nicht negativ und der Nenner positiv ist. Der Bruchzähler / Nenner muss der Eingabe entsprechen, wenn er korrekt auf n
Ziffern gerundet ist (dh n-1
Ziffern nach dem Komma).
Einschränkung: Es ist nur eine Schleifenanweisung zulässig. Dies bedeutet, dass Sie nur eine einzige Schleifenanweisung (wie for
oder while
oder goto
usw.) sowie funktionale Schleifen wie map
oder fold
, die Code auf jedes Element einer Liste / eines Arrays anwenden) in Ihrem gesamten Code verwenden können, aber Sie können ihn "missbrauchen" oder benutze Rekursion etc.
Sie sollten eine Funktion schreiben. Wenn Ihre Sprache keine Funktionen hat (oder auch nicht), können Sie alternativ davon ausgehen, dass die Eingabe in einer Variablen gespeichert ist (oder über stdin eingegeben wird), und das Ergebnis ausdrucken oder in eine Datei schreiben. Die niedrigste Anzahl von Bytes gewinnt.
Runden
Die Rundung sollte nach den „herkömmlichen“ Rundungsregeln erfolgen. Wenn also die letzte Stelle, die abgeschnitten wird, 5 oder mehr beträgt, runden Sie auf und runden für alle anderen Fälle ab. Beispiel:
Beim Runden auf ergibt sich 4.5494
- 1 Ziffer: 5
- 2 Stellen: 4.5
- 3 Stellen: 4,55
- 4 Stellen: 4,549
Beispiele
Bitte geben Sie folgende und andere 'interessante' Testfälle an:
Input 1.7 Output 5/3
Input 0. Output 0/1
Input 0.001 Output 1/667
Input 3.1416 Output 355/113
quelle
repeat
erstellt eine unendliche Liste seines Arguments. Es scheint sich zu wiederholen, aber es hat tatsächlich die zeitliche Komplexität von O (1). Aber ich denke, es ist besser, jeden Fall einzeln zu sortieren, als keine funktionalen Sprachen zuzulassen.for n in numbers: f(g(n))
äquivalent zumap(f, map(g, numbers))
. Die Funktionsversion verwendetmap
zweimal, sollte das wirklich verboten sein?Antworten:
CJam,
414036 BytesAls nächstes wird die Eingabezeichenfolge in Q gespeichert, was in der Frage ausdrücklich erlaubt ist. Probieren Sie es online aus.
Testfälle
Wie es funktioniert
quelle
T-SQL 254
Während T-SQL für solche Dinge nicht wirklich geeignet ist, macht es Spaß, es zu versuchen. Die Leistung wird umso schlechter, je höher der Nenner ist. Es ist auf einen Nenner von 1000 begrenzt.
Eingabe ist eine Float-Variable @
Eine Aufschlüsselung der Abfrage
quelle
3.14159
und es gab mir ordnungsgemäß355/113
Haskell,
6259wenn nur die Namen nicht so lang wären ...
Dies ist eine Funktion, die einen
Rational
Wert zurückgibt.Erklärung: Die Funktion
approxRational
ist eine Funktion, die eine Gleitkommazahl und ein Gleitkommazahl-Epsilon annimmt und das einfachste Rationale zurückgibt, das sich im Abstandsepsilon der Eingabe befindet. Grundsätzlich wird die einfachste Annäherung des Schwimmers an einen rationalen Fehler in einer "verzeihlichen Fehler" -Distanz zurückgegeben.Nutzen wir diese Funktion für unsere Zwecke. Dazu müssen wir herausfinden, wie groß die Fläche der Floats ist, die sich auf die angegebene Zahl aufrunden. Wenn Sie dies in die
approxRational
Funktion aufnehmen, erhalten Sie die Antwort.Versuchen wir zum Beispiel 1.7. Der niedrigste auf 1,7 gerundete Float ist 1,65. Ein niedrigerer Wert wird nicht auf 1,7 gerundet. In ähnlicher Weise beträgt die Obergrenze der Floats, die auf 1,7 runden, 1,75.
beide grenzen sind die grenzen sind die eingabenummer +/- 0.05. es kann leicht gezeigt werden, dass dieser Abstand immer ist
5 * 10 ^ -(the length of the input - 1)
(der -1 ist, weil es immer ein '.' in der Eingabe gibt). ab hier ist der code ganz einfach.Testfälle:
bei "0" funktioniert es leider nicht weil die Parser-Funktion von Haskell ein
.
am Ende eines Floats nicht erkennt . Dies kann durch Ersetzenread s
durch für 5 Bytes behoben werdenread$s++"0"
.quelle
Ruby,
127125 BytesDefiniert eine Funktion,
f
die das Ergebnis als zurückgibtRational
. ZB wenn Sie diesen Code anhängenDu erhältst
Die Schleife ist über Nenner. Ich beginne mit dem vollen Bruch, zB
31416/10000
für das letzte Beispiel. Dann dekrementiere ich den Nenner, dekrementiere den Zähler proportional (und runde ihn). Wenn das resultierende Rational auf die gleiche Zahl wie die eingegebene gerundet wird, erinnere ich mich an einen neuen besten Bruch.quelle
Mathematica,
4953 ZeichenVerwendung:
Ausgabe:
Testfälle:
Der 0,001-Fall kommt mir merkwürdig vor; da die Rationalisierungsfunktion nicht gemäß ihrer Beschreibung funktionierte, als sie den 1/667-Fall nicht fand. Sie sollte die Zahl mit dem kleinsten Nenner ausgeben, der innerhalb der angegebenen Grenzen liegt.
quelle
0.001
stimmt nicht mit dem OP überein, daRationalize
nicht die Einschränkung besteht, den Nenner zu minimieren. Wie ich dem stolzen Haskeller bereits sagte, ist eine rationale Approximationsfunktion zur Minimierung des Nenners hochgradig esoterisch (kurz gesagt, weil sie eine miese und ineffiziente Methode zur Approximation von Zahlen ist). Normalerweise würde ich nicht erwarten, dass es sich um eine Standardbibliotheksfunktion handelt.1/999
. 999 wird der (akzeptable) kleinste Nenner nur für einen Fehler zwischen ungefähr 1e-6 und 2e-6. Die Fehlergrenze liegt eindeutig bei 5e-4. Was auch immer Mathematica in diesem Fall tut, es funktioniert definitiv nicht nach Spezifikation. : PPython 2.7+, 111 Zeichen
Beweis, dass Sie schrecklichen Code in jeder Sprache schreiben können:
Ausgabe
quelle
APL, 50
Solange Sie nicht zählen
eval
undtoString
als SchleifenErläuterung
Der Ansatz besteht darin, als Nenner über 1 bis 10000 zu iterieren und den Zähler zu berechnen, der am ehesten mit dem Gleitkomma übereinstimmt, und dann zu prüfen, ob der Fehler innerhalb der Grenzen liegt. Zuletzt wählen Sie aus allen gefundenen Brüchen das kleinste Paar aus.
(⍎x←⍞)
String-Eingabe vom Bildschirm nehmen, zuweisenx
und auswerten⍳1e5
Array von 1 bis 10000 generieren{...}¨
Für jedes Element des Arrays Funktion damit aufrufen und(⍎x←⍞)
und Argumente (Schleife)⍺×⍵
Multiplizieren die Argumente⌊.5+
Abrunden (um 0,5 dann Abrunden Zugabe)n←
Zuweisen zun
⍺-⍵÷⍨
Divide by rechtem Argumente, dann subtrahiert linkes Argument(10*⍴x)×
Multiplizieren mit 10 auf die Kraft der „Länge vonx
“|
Absolutwert Nehmen50>
Sie prüfen , ob weniger als 50 (Länge vonx
2 mehr ist als die Nr. von dp, verwenden Sie hier also 50 anstelle von 0,5.):n ⍵⋄''
Wenn die vorherige Prüfung true zurückgibt, geben Sie das Array vonn
und das richtige Argument zurück, andernfalls wird eine leere Zeichenfolge zurückgegeben.⍎⍕
toString
und danneval
, um ein Array aller Zahlen im Array zu erhalten2↑
Wählen Sie nur die ersten 2 Elemente aus, bei denen es sich um das erste gefundene Zähler-Nenner-Paar handeltquelle
GNU DC, 72 Bytes
Keine Schleifen - DC hat sie nicht einmal. Stattdessen stammt die Steuerung aus einem einzelnen rekursiven Makro - idiomatisch für DC.
Ausgabe:
Puh. Teilweise Erklärung in dieser Antwort .
quelle
Mathematica, 111 Zeichen
Wirklich ziemlich einfach, und ich denke, es konvergiert nirgendwo so schnell wie die anderen Lösungen, da Zähler und Nenner nur um eins inkrementiert werden. Ich wollte meistens die einfache Lösung dafür finden. Ich muss die anderen Antworten sehen und sehen, was für clevere Sachen dort passieren.
Ausgabe
Feiert hier jemand den Pi Approximation Day ?
quelle
Applescript,> 300 Bytes
Ich wollte dies in einer Sprache tun, die von Haus aus die erforderliche Rundungsart bietet. Es stellt sich heraus, dass Applescript die Rechnung passt. Dann sah ich die Aufzählung
rounding as taught in school
und konnte der Verwendung nicht widerstehen, trotz der offensichtlichen Unwettbewerblichkeit von Applescript für Golfzwecke:Dies kann ein bisschen mehr Golf gespielt werden, aber wahrscheinlich nicht wert.
Ausgabe:
quelle
BC,
151148 BytesBearbeiten - schnellere und kürzere Version
gleicher Testfall.
Vieles ist ähnlich wie in der vorherigen Version, aber anstatt alle möglichen n / d-Kombinationen auszuprobieren, klettern wir über die Reste von v und Rückwärtsquotienten von Vielfachen von m == v * d und Nennern d. Auch hier ist die Genauigkeit der Berechnung gleich.
Hier ist es entwirrt:
Diese Version hat wirklich nur eine einzige Schleife und führt nur $ \ Theta \ left (\ operatorname {fractional_decimals} (v) \ right) $ arithmetische Operationen aus.
Original - langsame Version
Diese Funktion berechnet den kleinsten Nominator n und den kleinsten Nenner d so, dass der auf Nachkommastellen (v) gerundete Bruch n / d gleich einem gegebenen Dezimalwert v ist.
Testfall:
Und hier ist es entwirrt:
Ich gebe zu, ich habe ein wenig geschummelt, indem ich eine zweite innere Schleife innerhalb einer einzelnen äußeren Schleife emuliert habe, aber ohne weitere Schleifenanweisungen zu verwenden. Und deshalb führt es tatsächlich $ \ Theta \ left (v \ operatorname {fractional_decimals} (v) ^ 2 \ right) $ arithmetische Operationen aus.
quelle
C 233
Dies funktioniert durch Aufrufen einer Rationalisierungsfunktion r () mit einem Anfangsnenner von 1. Die Funktion beginnt mit dem Inkrementieren eines Zählers und prüft bei jedem Inkrement, ob die sich ergebende Zahl, wenn sie auf die gleiche Anzahl von Ziffern wie das Original gerundet wird, dieselbe Zeichenfolge hat Darstellung als Original. Sobald der Zähler so weit erhöht wurde, dass das Ergebnis größer als das Original ist, erhöht die Funktion den Nenner und ruft sich selbst auf.
Hier wird natürlich viel mehr Code verwendet, aber ich denke, der Geist des Problems entlastet diesen Bare-Bones-Ansatz. Soweit wir wissen, haben die internen rationalize () -Funktionen moderner Sprachen viele interne Schleifen.
Beachten Sie, dass dies bei einer Eingabe von "0" nicht funktioniert. Da dies keine Standardmethode zum Schreiben eines Floats ist, wird beim erneuten Schreiben des Floats in einen String niemals eine "0" ausgegeben.
Die Spezifikationen wollen eine Funktion, die Werte zurückgibt, anstatt nur auf dem Bildschirm zu drucken, daher die Übergabe von Argumenten.
Code (ungolfed):
Verwendung:
Golf Code:
quelle
approxRational
nur eine rekursive Hilfsfunktion und keine Schleife mehr.Pure Bash, 92 Bytes
Als eine teilweise Erklärung für diese Antwort wird hier portiert, um zu schlagen:
Vor allem:
Ausgabe:
quelle
int
Portierung auf cJavaScript (E6) 85
Ungolfed
Test In FireFox / Firebug - Konsole
Ausgabe
quelle