Ecco la chiave del tuo dilemma: 10
è il prodotto di 2
e 5
. Puoi rappresentare qualsiasi numero esattamente in decimali di base 10 che è k * 1/2 n * 1/5 m dove k
, n
e m
sono interi.
In alternativa formulato - se il numero n
in 1 / n contiene un fattore che non fa parte dei fattori della base, il numero non potrà essere rappresentato esattamente in un numero fisso di cifre nel binario / decimale / qualunque espansione di quel numero - avrà una parte ripetitiva. Per esempio 1/15 = 0.0666666666 .... perché 3 (15 = 3 * 5) non è un fattore di 10.
Quindi, tutto ciò che è in grado di essere rappresentato nella base 2 esattamente (k * 1/2 n ) può essere rappresentato esattamente nella base 10.
Oltre a ciò, c'è il problema di quante cifre / bit stai usando per rappresentare il numero. Ci sono alcuni numeri che possono essere esattamente rappresentati in alcune basi, ma ci vuole più di un numero di cifre / bit da fare.
In binario, il numero 1/10 che è convenientemente 0,1 in decimale non può essere rappresentato come un numero che può essere rappresentato in un numero fisso di bit in binario. Invece, il numero è 0.00011001100110011 ... 2 (con la parte 0011 che si ripete per sempre).
Diamo un'occhiata al numero 1 2 / 1010 2 un po 'più da vicino.
____
0.00011
+---------
1010 | 1.00000
0
--
1 0
0
----
1 00 ---------+
0 |
----- |
1 000 |
0 |
------ | repeating
1 0000 | block
1010 |
------ |
1100 |
1010 |
---- |
100 ----+
Questo è esattamente lo stesso tipo di cosa che ottieni quando provi a fare la divisione lunga per 1/3.
1/10, quando fattorizzato è 1 / (2 1 * 5 1 ). Per la base 10 (o qualsiasi multiplo di 10), questo numero termina ed è noto come numero normale . Un'espansione decimale che si ripete è conosciuta come ripetendo i decimali , e quei numeri che vanno avanti all'infinito senza ripetizione sono numeri irrazionali.
La matematica dietro a questo approfondisce Piccolo teorema di Fermat ... e una volta che inizi a dire Fermat o teorema, diventa un Domanda Math.SE .
Are there numbers that are not representable in base 10 but can be represented in base 2?
La risposta è "no".
Quindi, a questo punto dovremmo essere tutti chiari che ogni espansione binaria a lunghezza fissa di un numero razionale può essere rappresentata come un'espansione decimale a lunghezza fissa.
Consente di esaminare più da vicino il decimale in C # che ci porta a Virgola mobile decimale in .NET e dato all'autore, accetto che questo è il modo in cui funziona.
The decimal type has the same components as any other floating point number: a mantissa, an exponent and a sign. As usual, the sign is just a single bit, but there are 96 bits of mantissa and 5 bits of exponent. However, not all exponent combinations are valid. Only values 0-28 work, and they are effectively all negative: the numeric value is sign * mantissa / 10exponent
. This means the maximum and minimum values of the type are +/- (296-1), and the smallest non-zero number in terms of absolute magnitude is 10-28.
Indicherò subito che a causa di questa implementazione ci sono numeri nel tipo double
che non possono essere rappresentati in decimal
- quelli che sono fuori dall'intervallo. Double.Epsilon
è 4.94065645841247e-324
che non può essere rappresentato in decimal
, ma può in double
.
Tuttavia, all'interno dell'intervallo che può rappresentare un decimale, ha più precisione rispetto ad altri tipi nativi e può rappresentarli senza errori.
Ci sono altri tipi in giro. Esiste un BigInteger in C # che può rappresentare un numero arbitrariamente ampio. Non c'è alcun equivalente a BigDecimal di Java (che può rappresentare numeri con cifre decimali fino a 2 cifre 32 lunghe - che è un intervallo considerevole) esattamente . Tuttavia, se fai un po 'di movimento puoi trovare le implementazioni a mano.
Ci sono alcune lingue che hanno anche un tipo di dati razionale che ti permette di rappresentare esattamente i razionali (in modo che 1 / 3 è in realtà 1/3).
Specificamente per C # e la scelta di float o razionale, mi riferirò a Jon Skeet dalla pinta fluttuante decimale in. NET :
Most business applications should probably be using decimal rather than float or double. My rule of thumb is that manmade values such as currency are usually better represented with decimal floating point: the concept of exactly 1.25 dollars is entirely reasonable, for example. For values from the natural world, such as lengths and weights, binary floating point types make more sense. Even though there is a theoretical "exactly 1.25 metres" it's never going to occur in reality: you're certainly never going to be able to measure exact lengths, and they're unlikely to even exist at the atomic level. We're used to there being a certain tolerance involved.