Perché i numeri decimali non possono essere rappresentati esattamente in binario?


285

Sono state inviate a SO diverse domande sulla rappresentazione in virgola mobile. Ad esempio, il numero decimale 0.1 non ha una rappresentazione binaria esatta, quindi è pericoloso utilizzare l'operatore == per confrontarlo con un altro numero in virgola mobile. Comprendo i principi alla base della rappresentazione in virgola mobile.

Quello che non capisco è perché, dal punto di vista matematico, i numeri a destra del punto decimale sono più "speciali" di quelli a sinistra?

Ad esempio, il numero 61.0 ha una rappresentazione binaria esatta perché la parte integrale di qualsiasi numero è sempre esatta. Ma il numero 6.10 non è esatto. Tutto quello che ho fatto è stato spostare il decimale di un posto e improvvisamente sono passato da Exactopia a Inexactville. Matematicamente, non ci dovrebbero essere differenze intrinseche tra i due numeri: sono solo numeri.

Al contrario, se muovo il decimale di una posizione nell'altra direzione per produrre il numero 610, sono ancora in Exactopia. Posso continuare in quella direzione (6100, 610000000, 610000000000000) e sono ancora esatti, esatti, esatti. Ma non appena il decimale supera una soglia, i numeri non sono più esatti.

Cosa sta succedendo?

Modifica: per chiarire, voglio stare lontano dalla discussione sulle rappresentazioni standard del settore, come IEEE, e attenermi a quello che credo sia il modo matematicamente "puro". Nella base 10, i valori posizionali sono:

... 1000  100   10    1   1/10  1/100 ...

In binario, sarebbero:

... 8    4    2    1    1/2  1/4  1/8 ...

Non ci sono limiti arbitrari posti su questi numeri. Le posizioni aumentano indefinitamente a sinistra e a destra.


2
Potresti trovare utile capire esattamente cosa sta succedendo all'interno di un nubmber in virgola mobile: anatomia di un numero in virgola mobile .
John D. Cook,

57
In binario, il numero 3 è rappresentato come 2¹ + 2 ° = 2 + 1. Bello e facile. Ora dai un'occhiata a 1/3. Come lo rappresenteresti, usando poteri negativi di 2? Sperimenta un po 'e vedrai che 1/3 è uguale alla somma della sequenza infinita 2 ^ -2 + 2 ^ -4 + 2 ^ -6 + 2 ^ -8 + ..., cioè. non è così facile rappresentare l'esatto in binario.
Lars Haugseth,

21
Jon Skeet risponde molto bene alla domanda nel tuo corpo. Una cosa che manca è che in realtà fai due domande diverse. La domanda del titolo è "perché i numeri decimali non possono essere rappresentati esattamente in binario?" La risposta è che possono essere. Tra il titolo e il corpo confondi l'idea di "binario" e l'idea di una "rappresentazione in virgola mobile". Il virgola mobile è un modo per esprimere numeri decimali in un numero fisso di cifre binarie a scapito della precisione. Il binario è solo una base diversa per il conteggio e può esprimere qualsiasi numero decimale può, dato un numero infinito di cifre.
Chris Blackwell,

3
Esistono diversi sistemi con una rappresentazione decimale esatta. Funziona praticamente come descritto. Il tipo decimale SQL è un esempio. Le lingue LISP lo hanno incorporato. Esistono diverse librerie commerciali e opensource per l'utilizzo di calcoli decimali esatti. È solo che non esiste alcun supporto hardware per questo, e solo la maggior parte delle lingue e dell'hardware implementa gli standard IEEE per rappresentare una quantità infinita di numeri in 32 o 64 bit.
nn.

1
Questa domanda sembra fuori tema perché riguarda la matematica (anche se si tratta di matematica relativa alla programmazione) e sarebbe meglio in matematica
Cole Johnson,

Risposte:


360

I numeri decimali possono essere rappresentati esattamente, se si dispone di spazio sufficiente, semplicemente non facendo galleggiare i numeri di punti binari . Se si utilizza un tipo di virgola decimale mobile (ad es. System.DecimalIn .NET), è possibile rappresentare esattamente molti valori che non possono essere rappresentati esattamente in virgola mobile binaria.

Diamo un'occhiata in un altro modo: nella base 10 con cui probabilmente ti sentirai a tuo agio, non puoi esprimere esattamente 1/3. Sono 0.3333333 ... (ricorrenti). Il motivo per cui non è possibile rappresentare 0,1 come numero binario in virgola mobile è esattamente per lo stesso motivo. Puoi rappresentare esattamente 3, 9 e 27, ma non 1/3, 1/9 o 1/27.

Il problema è che 3 è un numero primo che non è un fattore 10. Non è un problema quando si desidera moltiplicare un numero per 3: è sempre possibile moltiplicare per un numero intero senza incorrere in problemi. Ma quando dividi per un numero che è primo e non è un fattore della tua base, puoi avere dei problemi (e lo farai se provi a dividere 1 per quel numero).

Sebbene 0.1 sia di solito usato come esempio più semplice di un numero decimale esatto che non può essere rappresentato esattamente in virgola mobile binaria, probabilmente 0.2 è un esempio più semplice in quanto è 1/5 - e 5 è il primo che causa problemi tra decimale e binario .


Nota a margine per affrontare il problema delle rappresentazioni finite:

Alcuni tipi di virgola decimale mobile hanno una dimensione fissa come System.Decimalaltri come java.math.BigDecimal"arbitrariamente grandi" - ma ad un certo punto colpiranno un limite, che si tratti di memoria di sistema o della dimensione massima teorica di un array. Questo è un punto completamente separato da quello principale di questa risposta, tuttavia. Anche se avessi un numero di bit veramente arbitrariamente grande con cui giocare, non potresti comunque rappresentare esattamente lo 0,1 decimale in una rappresentazione a virgola mobile. Confrontare che con il contrario: dato un numero arbitrario di cifre decimali, si può esattamente rappresentare qualsiasi numero che è esattamente rappresentabile come punto binario galleggiante.


8
Questo è un dannato esempio, signore!
Tom Ritter,

5
... vorrei poterlo votare due volte. Mi è stato chiesto di tutto questo troppe volte. È quasi come se la gente non potesse pensare al di fuori della base 10. hehe
Justin Niessner,

38
Sì, ci sono 10 tipi di persone al mondo - quelli che capiscono il binario e quelli che non lo fanno.
duffymo,

83
@JonSkeet: Ctrl + Alt + Canc apparirebbe imbarazzante con solo due dita.
Lars Haugseth,

20
@muusbolla: No. I numeri rappresentati dalla rappresentazione decimale 1e dalla rappresentazione decimale 0.9...(ripetendo all'infinito 9s dopo il punto decimale) sono uguali. Forse il modo più semplice per vederlo è il seguente: Let x = 0.9.... Si noti che 10x = 9.9..... Pertanto in 9x = 10x - x = 9.9... - 0.9... = 9modo che 9x = 9e x = 1. Ci sono altri modi per vederlo, ma credo che questo sia il più semplice.
Jason,

25

Ad esempio, il numero 61.0 ha una rappresentazione binaria esatta perché la parte integrale di qualsiasi numero è sempre esatta. Ma il numero 6.10 non è esatto. Tutto quello che ho fatto è stato spostare il decimale di un posto e improvvisamente sono passato da Exactopia a Inexactville. Matematicamente, non ci dovrebbero essere differenze intrinseche tra i due numeri: sono solo numeri .

Facciamo un passo indietro per un momento dai particolari delle basi 10 e 2. Chiediamo - in base b, quali numeri hanno rappresentazioni finali e quali numeri no? Il pensiero di un momento ci dice che un numero xha una rappresentazione bfinale se e solo se esiste un numero intero ntale che x b^nè un numero intero.

Quindi, per esempio, x = 11/500ha una rappresentazione finale di 10, perché possiamo scegliere n = 3e quindi x b^n = 22un numero intero. Tuttavia x = 1/3, perché qualunque ncosa scegliamo non saremo in grado di sbarazzarci del 3.

Questo secondo esempio ci spinge a pensare ai fattori, e possiamo vedere che per ogni razionale x = p/q (si presume che sia in termini più bassi), possiamo rispondere alla domanda confrontando le prime fattorizzazioni di be q. Se non ci qsono fattori primi nella fattorizzazione primaria b, non saremo mai in grado di trovare un adeguato nper sbarazzarci di questi fattori.

Pertanto, per la base 10, qualsiasi p/q dove qabbia fattori primi diversi da 2 o 5 non avrà una rappresentazione finale.

Quindi ora tornando alle basi 10 e 2, vediamo che qualsiasi razionale con una rappresentazione 10 terminante avrà la forma p/qesattamente quando qha solo 2s e 5s nella sua scomposizione in fattori primi; e quello stesso numero avrà una rappresentazione 2 terminante esattamente quando qha solo 2s nella sua scomposizione in fattori primi.

Ma uno di questi casi è un sottoinsieme dell'altro! Ogni volta

qha solo 2s nella sua scomposizione in fattori primi

è ovviamente anche vero

qha solo 2s e 5s nella sua scomposizione in fattori primi

o, in altri termini, ogni volta che p/qha una rappresentazione 2 terminante, p/qha una rappresentazione 10 terminante . Il contrario, tuttavia, non regge: ogni volta che qha un 5 nella sua scomposizione in fattori primi, avrà una rappresentazione 10 terminante, ma non una rappresentazione 2 terminante. Questo è l' 0.1esempio menzionato da altre risposte.

Quindi abbiamo la risposta alla tua domanda: poiché i fattori primi di 2 sono un sottoinsieme dei fattori primi di 10, tutti i numeri che terminano con 2 sono numeri che terminano con 10, ma non viceversa. Non è circa 61 contro 6.1 - è circa 10 contro 2.

Come nota di chiusura, se per alcune persone Quirk utilizzati (diciamo) base 17, ma i nostri computer utilizzati base 5, la vostra intuizione non sarebbe mai stato sviato da questo - non ci sarebbe nessun (non-zero non interi,) numeri che terminavano in entrambi i casi!


Allora perché "alert (0.15 * 0.15)" visualizza "0.0225"?
Michael Geiser,

5
Risposta breve di @MichaelGeiser: arrotondamento nel punto di visualizzazione. Quello che pensi è in 0.15realtà (se archiviato come doppio IEEE) `0.149999999999999994448884876874`. Vedi jsfiddle .
AakashM,

Bello chiaro esempio di codice punto! Vorrei poterti dare un voto positivo per questo! Devo giocare con alcune funzioni per esplorare dove si verifica il taglio arrotondato. Sono ancora stupito che dobbiamo davvero occuparci di questa spazzatura; dal momento che le persone lavorano nella base dieci quasi il 100% delle volte e utilizziamo non interi per così tanto tempo che penseresti che l'implementazione predefinita della matematica in virgola mobile gestirà questa assurdità.
Michael Geiser,

1
@MichaelGeiser i circuiti per lavorare con la base 2 sono più piccoli, più veloci e più efficienti dal punto di vista energetico rispetto a quelli con la base 10. Oggi potremmo essere in grado di giustificare il sovraccarico ma negli anni '70, quando venivano stabiliti gli standard, era un grande affare. Cercare di farlo senza il supporto diretto dei circuiti del processore è ancora peggio, aspettarsi che ordini di differenze di grandezza nella velocità.
Mark Ransom,

Questa risposta spiega meglio dello stesso Jon Skeet!
goelakash,

16

La ragione principale (matematica) è che quando si ha a che fare con numeri interi, essi sono infinitamente numerabili .

Il che significa che, anche se ce ne sono infiniti, potremmo "contare" tutti gli elementi nella sequenza, senza saltarne nessuno. Ciò significa che se vogliamo ottenere l'elemento nella 610000000000000terza posizione nell'elenco, possiamo capirlo tramite una formula.

Tuttavia, i numeri reali sono infinitamente infiniti . Non puoi dire "dammi il numero reale in posizione 610000000000000" e ottenere una risposta. Il motivo è perché, anche tra 0e 1, esiste un numero infinito di valori, quando si considerano valori in virgola mobile. Lo stesso vale per due numeri in virgola mobile.

Ulteriori informazioni:

http://en.wikipedia.org/wiki/Countable_set

http://en.wikipedia.org/wiki/Uncountable_set

Aggiornamento: mi scuso, sembra che abbia frainteso la domanda. La mia risposta è sul perché non possiamo rappresentare ogni valore reale , non avevo capito che il virgola mobile veniva automaticamente classificato come razionale.


6
In realtà, i numeri razionali sono numericamente infiniti. Ma non tutti i numeri reali sono numeri razionali. Posso certamente produrre una sequenza di numeri decimali esatti che raggiungeranno qualsiasi numero decimale esatto che vuoi darmi alla fine. È se hai bisogno di occuparti anche di numeri irrazionali che arrivi a insiemi infiniti infiniti.
Jon Skeet,

Vero, dovrei dire "reale", non "virgola mobile". Chiarirà.
TM.

1
A quel punto la logica diventa meno applicabile, IMO - perché non solo non possiamo gestire tutti i numeri reali usando il virgola mobile binario, ma non possiamo nemmeno gestire tutti i numeri razionali (come 0,1). In altre parole, non penso che abbia davvero a che fare con la numerabilità :)
Jon Skeet,

@jonskeet So che non essere d'accordo con Jon Skeet infrangerebbe una legge fondamentale della natura, quindi ovviamente non lo farò :) Tuttavia, penso che sia giusto pensare alla rappresentazione interna dei numeri come indici di un insieme dei valori che si desidera rappresentare esternamente. Con questa linea di pensiero, si può vedere che non importa quanto grande la vostra lista degli indici è (anche se tu avessi diciamo, infiniti bit di precisione), è ancora non sarebbe in grado di rappresentare tutti i numeri reali.
TM.

3
@TM: Ma l'OP non sta cercando di rappresentare tutti i numeri reali. Sta cercando di rappresentare tutti i numeri decimali esatti , che è un sottoinsieme dei numeri razionali e quindi solo infinitamente numerabile. Se stesse usando una serie infinita di bit come tipo decimale in virgola mobile, allora starebbe bene. Sta usando quei bit come tipo binario a virgola mobile che causa problemi con i numeri decimali.
Jon Skeet,

10

Per ripetere quello che ho detto nel mio commento al signor Skeet: siamo in grado di rappresentare 1/3, 1/9, 1/27, o qualsiasi razionale in notazione decimale. Lo facciamo aggiungendo un simbolo in più. Ad esempio, una linea sopra le cifre che si ripetono nell'espansione decimale del numero. Ciò di cui abbiamo bisogno per rappresentare i numeri decimali come una sequenza di numeri binari sono 1) una sequenza di numeri binari, 2) un punto radicale e 3) qualche altro simbolo per indicare la parte ripetitiva della sequenza.

La notazione di citazione di Hehner è un modo per farlo. Usa un simbolo di citazione per rappresentare la parte ripetitiva della sequenza. L'articolo: http://www.cs.toronto.edu/~hehner/ratno.pdf e la voce di Wikipedia: http://en.wikipedia.org/wiki/Quote_notation .

Non c'è nulla che dica che non possiamo aggiungere un simbolo al nostro sistema di rappresentazione, quindi possiamo rappresentare razionali decimali usando esattamente la notazione binaria e viceversa.


Tale sistema di notazione funziona se sappiamo dove inizia e finisce il ciclo. Gli umani sono abbastanza bravi a rilevare i cicli. Ma, in generale, i computer non lo sono. Per poter utilizzare un simbolo di ripetizione in modo efficace, il computer dovrebbe essere in grado di capire dove si trovano i cicli dopo aver effettuato un calcolo. Per il numero 1/3, ad esempio, il ciclo inizia immediatamente. Ma per il numero 1/97, il ciclo non si mostra fino a quando non hai elaborato la risposta ad almeno 96 cifre. (In realtà, avresti bisogno di 96 * 2 + 1 = 193 cifre per esserne sicuro.)
Barry Brown

4
In realtà non è affatto difficile per il computer rilevare il ciclo. Se leggi il documento di Hehner, descrive come rilevare i cicli per le varie operazioni aritmetiche. Ad esempio, nell'algoritmo di divisione, che utilizza ripetute sottrazioni, sai dove inizia il ciclo quando vedi una differenza che hai visto prima.
ntownsend,

3
Inoltre, la domanda riguardava la rappresentazione esatta dei numeri. A volte la rappresentazione esatta significa molti bit. La bellezza della notazione di citazione è che Hehner dimostra che in media si ha un risparmio del 31% nella dimensione della rappresentazione rispetto alla rappresentazione standard a lunghezza fissa a 32 bit.
ntownsend,

6

BCD - Decimale con codice binario - le rappresentazioni sono esatte. Non sono molto efficienti in termini di spazio, ma questo è un compromesso che devi fare per la precisione in questo caso.


1
I BCD non sono più o meno esatti di qualsiasi altra base. Esempio: come si rappresenta 1/3 esattamente in BCD? Non puoi.
Jörg W Mittag,

12
BCD è una rappresentazione esatta di un DECIMALE, quindi la parte "decimale" del suo nome. Non esiste neanche una rappresentazione decimale esatta di 1/3.
Alan,

4

È la stessa ragione per cui non puoi rappresentare 1/3 esattamente nella base 10, devi dire 0.33333 (3). In binario è lo stesso tipo di problema ma si verifica solo per diversi set di numeri.


4

(Nota: aggiungerò 'b' per indicare i numeri binari qui. Tutti gli altri numeri sono indicati in decimali)

Un modo di pensare alle cose è in termini di qualcosa come la notazione scientifica. Siamo abituati a vedere numeri espressi in notazione scientifica come 6.022141 * 10 ^ 23. I numeri in virgola mobile sono memorizzati internamente usando un formato simile - mantissa ed esponente, ma usando potenze di due invece di dieci.

Il tuo 61.0 potrebbe essere riscritto come 1.90625 * 2 ^ 5 o 1.11101b * 2 ^ 101b con la mantissa e gli esponenti. Per moltiplicarlo per dieci e (spostare il punto decimale), possiamo fare:

(1.90625 * 2 ^ 5) * (1.25 * 2 ^ 3) = (2.3828125 * 2 ^ 8) = (1.19140625 * 2 ^ 9)

o dentro con la mantissa e gli esponenti in binario:

(1.11101b * 2 ^ 101b) * (1.01b * 2 ^ 11b) = (10.0110001b * 2 ^ 1000b) = (1.00110001b * 2 ^ 1001b)

Nota cosa abbiamo fatto lì per moltiplicare i numeri. Abbiamo moltiplicato le mantisse e aggiunto gli esponenti. Quindi, poiché la mantissa finiva più di due, abbiamo normalizzato il risultato urtando l'esponente. È proprio come quando regoliamo l'esponente dopo aver fatto un'operazione sui numeri in notazione scientifica decimale. In ogni caso, i valori con cui abbiamo lavorato avevano una rappresentazione finita in binario, quindi i valori emessi dalle operazioni di moltiplicazione e addizione di base producevano anche valori con una rappresentazione finita.

Ora, considera come divideremo 61 per 10. Iniziamo dividendo le mante, 1.90625 e 1.25. In decimale, questo dà 1,525, un bel numero breve. Ma cos'è questo se lo convertiamo in binario? Lo faremo nel solito modo - sottraendo la più grande potenza di due quando possibile, proprio come convertire i decimali di numeri interi in binario, ma useremo i poteri negativi di due:

1.525 - 1 * 2 ^ 0 -> 1
0,525 - 1 * 2 ^ -1 -> 1
0,025 - 0 * 2 ^ -2 -> 0
0,025 - 0 * 2 ^ -3 -> 0
0,025 - 0 * 2 ^ -4 -> 0
0,025 - 0 * 2 ^ -5 -> 0
0,025 - 1 * 2 ^ -6 -> 1
0,009375 - 1 * 2 ^ -7 -> 1
0,0015625 - 0 * 2 ^ -8 -> 0
0,0015625 - 0 * 2 ^ -9 -> 0
0,0015625 - 1 * 2 ^ -10 -> 1
0.0005859375 - 1 * 2 ^ -11 -> 1
,00009765625 ...

Uh Oh. Ora siamo nei guai. Si scopre che 1.90625 / 1.25 = 1.525, è una frazione ripetitiva quando espressa in binario: 1.11101b / 1.01b = 1.10000110011 ... b Le nostre macchine hanno solo così tanti bit per contenere quella mantissa e quindi arrotondano solo la frazione e assumere zero oltre un certo punto. L'errore che vedi quando dividi 61 per 10 è la differenza tra:

1.100001100110011001100110011001100110011 ... b * 2 ^ 10b
e, diciamo:
1.100001100110011001100110b * 2 ^ 10b

È questo arrotondamento della mantissa che porta alla perdita di precisione che associamo ai valori in virgola mobile. Anche quando la mantissa può essere espressa esattamente (ad esempio, quando si aggiungono solo due numeri), possiamo comunque ottenere una perdita numerica se la mantissa necessita di troppe cifre per adattarsi dopo la normalizzazione dell'esponente.

In realtà facciamo questo genere di cose tutto il tempo quando arrotondiamo i numeri decimali a una dimensione gestibile e ne forniamo solo le prime cifre. Poiché esprimiamo il risultato in decimale, sembra naturale. Ma se arrotondassimo un decimale e lo convertissimo in una base diversa, sembrerebbe brutto quanto i decimali che otteniamo a causa dell'arrotondamento in virgola mobile.


4

Questa è una buona domanda

Tutta la tua domanda si basa su "come rappresentiamo un numero?"

TUTTI i numeri possono essere rappresentati con rappresentazione decimale o con rappresentazione binaria (complemento di 2). Tutti loro !!

MA alcuni (la maggior parte di essi) richiedono un numero infinito di elementi (da "0" o "1" per la posizione binaria, o da "0", da "1" a "9" per la rappresentazione decimale).

Come 1/3 nella rappresentazione decimale (1/3 = 0.3333333 ... <- con un numero infinito di "3")

Come 0,1 in binario (0,1 = 0,00011001100110011 .... <- con un numero infinito di "0011")

Tutto è in questo concetto. Poiché il tuo computer può prendere in considerazione solo un set di cifre finito (decimale o binario), solo alcuni numeri possono essere rappresentati esattamente nel tuo computer ...

E come detto Jon, 3 è un numero primo che non è un fattore 10, quindi 1/3 non può essere rappresentato con un numero finito di elementi nella base 10.

Anche con aritmetica con precisione arbitraria, il sistema di posizione di numerazione nella base 2 non è in grado di descrivere completamente 6.1, sebbene possa rappresentare 61.

Per 6.1, dobbiamo usare un'altra rappresentazione (come la rappresentazione decimale o IEEE 854 che consente la base 2 o la base 10 per la rappresentazione di valori in virgola mobile)


Potresti rappresentare 1/3 come la frazione stessa. Non è necessario un numero infinito di bit per rappresentarlo. Lo rappresenti semplicemente come la frazione 1/3, invece del risultato di prendere 1 e dividerlo per 3. Diversi sistemi funzionano in questo modo. Quindi hai bisogno di un modo per usare lo standard / * + - e operatori simili per lavorare sulla rappresentazione delle frazioni, ma è abbastanza facile - puoi fare quelle operazioni con carta e penna, insegnare a un computer a farlo non è un grosso problema .
nn.

Stavo parlando di "rappresentazione binaria (complemento a 2)". Perché, naturalmente, l'uso di un'altra rappresentazione può aiutarti a rappresentare un numero con un numero finito di elementi (e avrai bisogno di un numero infinito di elementi per alcuni altri)
ThibThib

3

Se fai un numero abbastanza grande con virgola mobile (come può fare esponenti), finirai anche con inesattezza davanti al punto decimale. Quindi non penso che la tua domanda sia del tutto valida perché la premessa è sbagliata; non è il caso che lo spostamento di 10 creerà sempre più precisione, perché ad un certo punto il numero in virgola mobile dovrà usare esponenti per rappresentare la grandezza del numero e perderà anche una certa precisione in quel modo.


3

Sono sorpreso che nessuno lo abbia ancora dichiarato: usa le frazioni continue . In questo modo qualsiasi numero razionale può essere rappresentato in modo fine in binario.

Qualche esempio:

1/3 (0,3333 ...)

0; 3

5/9 (0,5555 ...)

0; 1, 1, 4

10/43 (0.232558139534883720930 ...)

0; 4, 3, 3

9093/18478 (0.49209871198181621387596060179673 ...)

0; 2, 31, 7, 8, 5

Da qui, ci sono una varietà di modi noti per memorizzare una sequenza di numeri interi in memoria.

Oltre a memorizzare il numero con la massima precisione, le frazioni continue offrono anche altri vantaggi, come la migliore approssimazione razionale. Se decidi di terminare anticipatamente la sequenza di numeri in una frazione continua, le cifre rimanenti (se ricombinate in una frazione) ti daranno la frazione migliore possibile. Ecco come si trovano le approssimazioni al pi:

La frazione continua di Pi:

3; 7, 15, 1, 292 ...

Terminando la sequenza su 1, questo dà la frazione:

355/113

che è un'eccellente approssimazione razionale.


Ma come lo rappresenteresti in binario? Ad esempio 15 richiede che vengano rappresentati 4 bit, ma 292 richiede 9. In che modo l'hardware (o anche il software) sa dove si trovano i limiti dei bit tra ciascuno? È il rapporto tra efficienza e precisione.
ardente

2

Nell'equazione

2^x = y ;  
x = log(y) / log(2)

Quindi, mi stavo solo chiedendo se potessimo avere un sistema di base logaritmico per binari come,

 2^1, 2^0, 2^(log(1/2) / log(2)), 2^(log(1/4) / log(2)), 2^(log(1/8) / log(2)),2^(log(1/16) / log(2)) ........

Potrebbe essere in grado di risolvere il problema, quindi se si volesse scrivere qualcosa come 32.41 in binario, sarebbe

2^5 + 2^(log(0.4) / log(2)) + 2^(log(0.01) / log(2))

O

2^5 + 2^(log(0.41) / log(2))

1

Il problema è che non sai davvero se il numero è esattamente 61.0. Considera questo:


float a = 60;
float b = 0.1;
float c = a + b * 10;

Qual è il valore di c? Non è esattamente 61, perché b non è in realtà .1 perché .1 non ha una rappresentazione binaria esatta.


1

C'è una soglia perché il significato della cifra è passato da intero a non intero. Per rappresentare 61, hai 6 * 10 ^ 1 + 1 * 10 ^ 0; 10 ^ 1 e 10 ^ 0 sono entrambi numeri interi. 6.1 è 6 * 10 ^ 0 + 1 * 10 ^ -1, ma 10 ^ -1 è 1/10, che sicuramente non è un numero intero. È così che finisci a Inexactville.


1

Un parallelo può essere fatto di frazioni e numeri interi. Alcune frazioni, ad esempio 1/7, non possono essere rappresentate in forma decimale senza lotti e molti decimali. Poiché il virgola mobile è basato su binari, i casi speciali cambiano ma si presentano gli stessi problemi di precisione.


0

Esiste un numero infinito di numeri razionali e un numero finito di bit con cui rappresentarli. Vedi http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems .


Ma anche con un numero infinito di bit, se avessi usato un punto binario mobile, non saresti ancora in grado di rappresentare 0,1 esattamente, proprio come non puoi rappresentare 1/3 esattamente in decimale anche con un numero infinito di bit.
Jon Skeet,

3
@Jon È falso: con un numero infinito di decimali, ad esempio , posso esprimere esattamente un terzo . Il problema del mondo reale è che non è fisicamente possibile avere "un numero infinito" di decimali o di bit.
ChrisW,

0

Il numero 61.0 ha effettivamente un'operazione in virgola mobile esatta, ma non è vero per tutti i numeri interi. Se hai scritto un ciclo che ne ha aggiunto uno sia a un numero in virgola mobile a doppia precisione sia a un numero intero a 64 bit, alla fine raggiungeresti un punto in cui l'intero a 64 bit rappresenta perfettamente un numero, ma il punto mobile non lo fa— perché non ci sono abbastanza bit significativi.

È molto più semplice raggiungere il punto di approssimazione sul lato destro del punto decimale. Se hai iniziato a scrivere tutti i numeri in virgola mobile binaria, avrebbe più senso.

Un altro modo di pensarci è che quando noti che 61.0 è perfettamente rappresentabile nella base 10, e spostando il punto decimale non cambia ciò, stai eseguendo la moltiplicazione per potenze di dieci (10 ^ 1, 10 ^ -1 ). In virgola mobile, la moltiplicazione per potenze di due non influisce sulla precisione del numero. Prova a prendere 61.0 e dividerlo per tre ripetutamente per un'illustrazione di come un numero perfettamente preciso può perdere la sua rappresentazione precisa.


0

conosci numeri interi vero? ogni bit rappresenta 2 ^ n


2 ^ 4 = 16
2 ^ 3 = 8
2 ^ 2 = 4
2 ^ 1 = 2
2 ^ 0 = 1

bene è lo stesso per il virgola mobile (con alcune distinzioni) ma i bit rappresentano 2 ^ -n 2 ^ -1 = 1/2 = 0.5
2 ^ -2 = 1 / (2 * 2) = 0.25
2 ^ -3 = 0.125
2 ^ -4 = 0,0625

Rappresentazione binaria in virgola mobile:

segno Frazione esponente (penso che invisibile 1 sia aggiunto alla frazione)
B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0


0

La risposta al punteggio più alto sopra l'ha inchiodata.

Prima stavi mescolando la base 2 e la base 10 nella tua domanda, poi quando metti un numero sul lato destro che non è divisibile nella base ottieni problemi. Come 1/3 in decimale perché 3 non va in una potenza di 10 o 1/5 in binario che non va in una potenza di 2.

Un altro commento sebbene MAI usare uguale con numeri in virgola mobile, punto. Anche se è una rappresentazione esatta ci sono alcuni numeri in alcuni sistemi a virgola mobile che possono essere rappresentati in modo accurato in più di un modo (IEEE non va bene in questo, è una orribile specifica in virgola mobile da cui iniziare, quindi aspettatevi mal di testa). Non differisce qui 1/3 non è UGUALE al numero sulla calcolatrice 0.3333333, indipendentemente dal numero di 3 a destra del punto decimale. È o può essere abbastanza vicino ma non è uguale. quindi ti aspetteresti che qualcosa come 2 * 1/3 non sia uguale a 2/3 a seconda dell'arrotondamento. Non usare mai uguale a virgola mobile.


0

Come abbiamo discusso, nell'aritmetica in virgola mobile, lo 0,1 decimale non può essere rappresentato perfettamente in binario.

Le rappresentazioni in virgola mobile e in numero intero forniscono griglie o reticoli per i numeri rappresentati. Man mano che l'aritmetica viene eseguita, i risultati cadono dalla griglia e devono essere rimessi sulla griglia arrotondando. L'esempio è 1/10 su una griglia binaria.

Se utilizziamo la rappresentazione decimale con codice binario come suggerito da un gentiluomo, saremmo in grado di mantenere i numeri sulla griglia?


1
Numeri decimali, certo. Ma questo è solo per definizione. Non puoi rappresentare 1/3 in decimale, non più di quanto puoi rappresentare 0,1 in binario. Qualsiasi schema di quantizzazione fallisce per un numero infinitamente grande di numeri.
Kylotan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.