2013-10-17 12 views
6

Matematicamente, 0 0 ricorrente può essere mostrato uguale a 1. Questa domanda tuttavia non riguarda l'infinito, la convergenza o la matematica dietro a questo.Perché non 0.9 ricorrente sempre uguale 1

L'ipotesi sopra può essere rappresentata utilizzando i doppi in C# con il seguente.

var oneOverNine = 1d/9d; 
var resultTimesNine = oneOverNine * 9d; 

Utilizzando il codice sopra riportato, (resultTimesNine == 1d) è true.

Quando si utilizzano invece i decimali, la valutazione risulta falsa, tuttavia, la mia domanda non riguarda la disparità di precisione del doppio e del decimale.

Poiché nessun tipo ha una precisione infinita, come e perché raddoppiare mantiene tale uguaglianza laddove il decimale no? Cosa sta succedendo letteralmente "tra le righe" del codice sopra, per quanto riguarda il modo in cui la variabile oneOverNine è memorizzata?

+0

Suppongo che l'arrotondamento avvenga. Per i doppi verso '1.0', per i galleggianti lontano da esso. – millimoose

+1

Quale versione di C#, compilatore e sistema operativo? Chiedere perché l'uso di VS2010 su una macchina Win7 a 64 bit restituisce "true" per me sia per i float che per i double, sia che si tratti di x86 o x64. –

+0

@JoelRondeau Domanda giusta, sulla mia macchina attuale (VS2010, Win7 x64), ottengo gli stessi risultati come te, ma false per decimale, quindi ancora, differenze di precisione, ma interessanti per il confronto. –

risposta

11

Dipende dall'arrotondamento utilizzato per ottenere il valore rappresentativo più vicino a 1/9. Può andare in entrambi i modi. È possibile esaminare il problema della rappresentabilità alla pagina utile di Rob Kennedy: http://pages.cs.wisc.edu/~rkennedy/exact-float

Ma non pensare che in qualche modo il doppio sia in grado di raggiungere l'esattezza. Non lo è. Se provi con 2/9, 3/9 ecc. Troverai casi in cui l'arrotondamento va dall'altra parte. La linea di fondo è che 1/9 non è esattamente rappresentabile in virgola mobile. E così avviene l'arrotondamento e i tuoi calcoli sono soggetti a errori di arrotondamento.

2

Cosa sta accadendo letteralmente "tra le righe" del codice sopra, per quanto riguarda il modo in cui la variabile oneOverNine è memorizzata?

Quello che stai chiedendo si chiama IEEE 754. Questa è la specifica che C#, è il runtime .Net sottostante e la maggior parte delle altre piattaforme di programmazione usano per memorizzare e manipolare i valori decimali. Questo perché il supporto per IEEE 754 viene in genere implementato direttamente a livello di CPU/chipset, rendendo molto più performante di un'alternativa implementata esclusivamente nel software e molto più semplice quando si compilano i compilatori, poiché le operazioni verranno mappate quasi direttamente a specifiche istruzioni della CPU .

Problemi correlati