C#
hat den decimal
Typ, der für Zahlen verwendet wird, die in der Basis 10 genau dargestellt werden müssen. 0.1
Kann beispielsweise nicht in der Basis 2 dargestellt werden (z. B. float
und double
) und ist immer eine Näherung, wenn sie in Variablen dieser Typen gespeichert werden.
Ich fragte mich, ob die umgekehrte Tatsache auch möglich war. Gibt es Zahlen, die in der Basis 10 nicht darstellbar sind, aber in der Basis 2 dargestellt werden können (in welchem Fall möchte ich ein float
anstelle von einem verwenden decimal
, um damit umzugehen)?
0.11_b2
, schreiben Sie ihn als0.5 + 0.5 * 0.5
. Gibt es einen Schritt, der fehlschlagen oder zu einer wiederholten Dezimalstelle führen könnte? Persönlich finde ich, dass diese Übung großartige Arbeit leistet, um eine Vorstellung von Zahlen zur Basis 2 zu vermitteln. Ich nehme an, man könnte noch einen Schritt weiter gehen und diese Übung in einen konstruktiven Beweis verwandeln.0.0999999....998..
genau, aber nicht die vollständige Zahl darstellen.0.1
Näherungen wie das Runden auf Hunderte von Stellen0.100
sind ein Problem bei der Implementierung, bei dem nicht alle Stellen angezeigt und stattdessen gerundet werden.Antworten:
Hier ist der Schlüssel zu Ihrem Dilemma:
10
ist das Produkt von2
und5
. Sie können beliebig viele genau in der Basis 10 Dezimalzahlen darstellen , die k * 1/2 n * 1/5 m , wok
,n
undm
ganze Zahlen sind.Alternativ formuliert - Wenn die Zahl
n
in 1 / n einen Faktor enthält, der nicht Teil der Faktoren der Basis ist, kann die Zahl in der binären / dezimalen / beliebigen Erweiterung nicht genau mit einer festen Anzahl von Ziffern dargestellt werden number - es wird einen sich wiederholenden Teil haben. Zum Beispiel 1/15 = 0.0666666666 .... weil 3 (15 = 3 * 5) kein Faktor von 10 ist.Somit kann alles, was in der Basis 2 genau dargestellt werden kann (k · 1/2 n ), in der Basis 10 genau dargestellt werden.
Darüber hinaus gibt es die Frage, wie viele Stellen / Bits Sie zur Darstellung der Zahl verwenden. Es gibt einige Zahlen, die in einer Basis exakt dargestellt werden können, aber es sind mehr als einige Ziffern / Bits erforderlich, um dies zu tun.
In der Binärdarstellung kann die Zahl 1/10, die günstigerweise 0,1 dezimal ist, nicht als Zahl dargestellt werden, die in einer festen Anzahl von Bits in der Binärdarstellung dargestellt werden kann. Stattdessen lautet die Nummer 0.00011001100110011 ... 2 (wobei sich der 0011-Teil für immer wiederholt).
Lets Blick auf der Nummer 1 2 /1010 2 einen engen Bit.
Dies ist genau die gleiche Art von Dingen, die Sie erhalten, wenn Sie versuchen, die lange Division für 1/3 durchzuführen.
1/10, wenn berücksichtigt, ist 1 / (2 1 * 5 1 ). Für die Basis 10 (oder ein Vielfaches von 10) endet diese Nummer und wird als reguläre Nummer bezeichnet . Eine sich wiederholende Dezimalerweiterung wird als sich wiederholende Dezimalzahl bezeichnet , und diese Zahlen, die für immer ohne Wiederholung weitergehen, sind irrationale Zahlen.
Die Mathematik dahinter befasst sich mit Fermats kleinem Theorem ... und sobald Sie anfangen, Fermat oder Theorem zu sagen, wird es zu einer Math.SE-Frage .
Die Antwort ist nein'.
An dieser Stelle sollte uns allen klar sein, dass jede binäre Expansion einer rationalen Zahl mit fester Länge als dezimale Expansion mit fester Länge dargestellt werden kann.
Lets Blick stärker auf das Dezimalsystem in C # , die uns führt Gleitpunktberechnungen in .NET und den Autor gegeben, werde ich , dass das ist , akzeptieren , wie es funktioniert.
Ich werde gleich darauf hinweisen, dass es aufgrund dieser Implementierung Zahlen in dem
double
Typ gibt, die nicht dargestellt werden könnendecimal
- solche, die außerhalb des Bereichs liegen.Double.Epsilon
ist ,4.94065645841247e-324
die in einem nicht dargestellt werden könnendecimal
, sondern in einemdouble
.Innerhalb des Bereichs, den die Dezimalzahl darstellen kann, hat sie jedoch eine höhere Genauigkeit als andere native Typen und kann sie fehlerfrei darstellen.
Es gibt einige andere Typen, die herumschweben. In C # gibt es eine BigInteger- Zahl, die eine beliebig große Ganzzahl darstellen kann. Es gibt kein Äquivalent zu Java BigDecimal (die Zahlen nach oben mit Dezimalstellen von bis zu 2 darstellen kann 32 Ziffern lang - das ist eine beträchtliche Reichweite ist) genau . Wenn Sie jedoch ein wenig herumstöbern, finden Sie handgerollte Implementierungen.
Es gibt einige Sprachen, die auch einen rationalen Datentyp haben , mit dem Sie Rationales genau darstellen können (so dass 1/3 tatsächlich 1/3 ist).
Speziell für C # und die Wahl zwischen Float und Rational werde ich mich von dem Pint Decimal Floating in .NET an Jon Skeet wenden :
quelle
n = 15
undb = 10
sind nicht relativ prim ("teile keine gemeinsamen positiven Faktoren (Teiler) außer 1"), weil sie 5 als Faktor teilen. Der Schlüssel ist, dass nicht alle Faktoren von 15 (5 und 3) auch Faktoren von 10 sind. (Abgesehen davon: Gibt es ein Wort, das Zahlen angibt, die alle gemeinsamen Faktoren teilen oder nicht?) Ich denke, das ist ordentlich in deinek, n, m
Gleichung eingewickelt , aber um meinen Kopf wirklich darum zu wickeln, müsste ich einen 3D-Plot sehen. Unabhängig davon, gut verdient +1 für Sie.Sobald Sie den zulässigen Wertebereich verlassen haben, lautet die Antwort "Ja". Das heißt, fast alles innerhalb des Bereichs wird eine Darstellung haben. C # -Dezimalreferenz Obwohl in der Spezifikation nicht angegeben, können irrationale Zahlen nicht genau dargestellt werden (z. B. e 1 , pi, Quadratwurzel von 2 usw.).
1 Danke an MichaelT, der mich an eine andere irrationale Zahl erinnert hat.
quelle
e
(2.71 ...). Das natürliche log - ln (x) ist die logarithmische Basis e. Somit existieren irrationale Grundlagen und sind nützlich. Die besondere Nützlichkeit von Basis-Pi weiß ich nicht genau - aber das heißt nicht, dass es nicht irgendwo verwendet wird.Ein Gleitkommatyp mit Basis zwei könnte viele Werte präzise darstellen, die ein Typ mit Basis zehn derselben Größe nicht darstellen könnte. Jeder Wert, der durch einen Basis-2-Typ einer bestimmten Größe genau darstellbar wäre, wäre in einem Basis-10-Typ einer ausreichenden Größe genau darstellbar. Die erforderliche Größe für einen reinen Zehnerbasistyp zur Darstellung aller Werte einer binären Gleitkommazahl hängt vom Exponentenbereich des binären Typs ab. Hunderte von Bits für a
float
oder Tausende für adouble
.Abgesehen davon ist der
Decimal
Typ groß genug, um ihn als "universellen" Typ nutzbar zu machen, der den Wert eines anderen numerischen Grundelements aufnehmen und einige andere zusätzliche Merkmale bereitstellen kann (wenn nichts anderes, verwenden Sie ein Bit) Um anzuzeigen, ob der gespeicherte Wert das Ergebnis der Konvertierung von a istdouble
, und wenn dieses Bit gesetzt ist, verwenden Sie 64 Bit, um den betreffenden Wert zu speichern . Microsoft hat sich jedoch dagegen entschieden. Infolgedessen schlägt die Konvertierung von adouble
zuDecimal
für große Werte vollständig fehl und kleine Werte werden auf die nächste 1E-28 gerundet. Weiterhin auch im Dynamikbereich vondecimal
wird die Konvertierungsmethode nicht "Roundtrip". Wenn Sie beispielsweise 1,0 / 3,0 als doppelt auswerten, erhalten Sie 0,3333333333333333148, wenn Sie dies jedoch in dezimal umwandeln, erhalten Sie 0,3333333333333m, und wenn Sie dies zurück in doppelt umwandeln, erhalten Sie 0,33333333333329818.quelle