Questo non ha davvero nulla a che fare con Python - si vedrebbe lo stesso comportamento in qualsiasi lingua usando l'aritmetica in virgola mobile binaria dell'hardware. Primo read the docs.
Dopo aver letto questo, capirai meglio che sei non aggiungendo un centesimo nel tuo codice. Questo è esattamente ciò che si sta aggiungendo:
>>> from decimal import Decimal
>>> Decimal(.01)
Decimal('0.01000000000000000020816681711721685132943093776702880859375')
quella stringa mostra l'esatto valore decimale del binario galleggiante ("doppia precisione" in C) approssimazione al valore esatto decimali 0,01. La cosa che stai davvero aggiungendo è un po 'più grande di 1/100.
Controllare gli errori numerici a virgola mobile è il campo denominato "analisi numerica" ed è un argomento molto ampio e complesso. Finché sei sorpreso dal fatto che i float sono solo approssimazioni ai valori decimali, usa il modulo decimal
. Ciò porterà via un mondo di problemi "superficiali" per te. Ad esempio, data questa piccola modifica alla funzione:
from decimal import Decimal as D
def sqrt(num):
root = D(0)
while root * root < num:
root += D("0.01")
return root
poi:
>>> sqrt(4)
Decimal('2.00')
>>> sqrt(9)
Decimal('3.00')
Non è davvero più accurato, ma può essere meno sorprendente in semplici esempi perché ora è l'aggiunta di esattamente uno uno -centesimo.
Un'alternativa è quella di attenersi a carri e aggiungere qualcosa che è esattamente rappresentabili come float binario: i valori del modulo I/2**J
. Ad esempio, anziché aggiungere 0.01, aggiungere 0.125 (1/8) o 0.0625 (1/16).
allora sotto "il metodo di Newton" per calcolare le radici quadrate ;-)
fonte
2013-10-20 04:18:20
Forse provare il modulo [decimale] (http://docs.python.org/2/library/decimal.html), che è progettato per la precisione? – Michael0x2a