2014-12-26 22 views
5

Perché questa asserzione fallisce?Perché non deve! Int() funzionare correttamente?

import std.conv; 

void main() 
{ 
    auto y = 0.6, delta=0.1; 
    auto r = to!int(y/delta); 
    assert(r == 6); 
} 

valore di r deve essere 6 e tuttavia è 5, perché?

+3

[La matematica in virgola mobile è rotta?] (Http://stackoverflow.com/questions/588004/is-floating-point -math-broken) [Ciò che ogni programmatore dovrebbe sapere circa l'aritmetica a virgola mobile] (http://floating-point-gui.de/) –

+2

dopo che leggi questo approfondito articolo [Ciò che ogni scienziato informatico dovrebbe sapere riguardo all'aritmetica virgola mobile ] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) –

risposta

5

Ciò è probabilmente dovuto al fatto che 0.6 non può essere rappresentato puramente in un numero in virgola mobile. Scrivi 0.6, ma non è esattamente quello che ottieni - ottieni qualcosa come 0.599999999. Quando lo dividi per 0,1, ottieni qualcosa come 5.99999999, che converte in un numero intero di 5 (arrotondando per difetto).

Esempi in altre lingue:

C#: Why is (double)0.6f > (double)(6/10f)?

Java: Can someone please explain me that in java why 0.6 is <0.6f but 0.7is >=0.7f

+1

Come posso arrotondare? – Algo

+2

È possibile arrotondare al numero intero più vicino con std.math.round: http://dlang.org/library/std/math/round.html. Se sai che il tuo risultato in virgola mobile è compreso tra 0,5 del numero intero che vuoi, questo arrotonda il risultato a ciò che desideri. Due risposte al prezzo di una! –

+0

Oppure aggiungendo 0.5. Io uso (y/delta + 0.5) – runec

4

Computer rappresentano numeri in virgola mobile nel sistema binario. I numeri decimali 0,6 e 0,1 non hanno una rappresentazione binaria esatta, mentre il numero di bit usati per rappresentarli è finito. Di conseguenza, ci sarebbe il troncamento, il cui effetto è visto durante la divisione. Il risultato di tale divisione non è esattamente 6.00000000, ma forse 5.99999999, che viene quindi troncato a 5.