io sospetto la differenza è una conversione da un valore a virgola mobile 80-bit per una lunga vs una conversione da un valore a virgola mobile 80 bit a 64 bit uno e poi una conversione per un lungo.
(La ragione di 80 bit in arrivo a tutti è che questo è un tipico precisione utilizzato per aritmetica effettivo, e la larghezza dei registri in virgola mobile.)
Supponiamo il risultato di 80 bit è qualcosa di simile 10,999999999999999 - la conversione da quella ad una lunga resa 10. Tuttavia, il valore a virgola mobile a 64 bit più vicino al valore di 80-bit è in realtà 11.0, quindi la conversione a due stadi termina producendo 11.
EDIT: Per dare a questo un un po 'più di peso ...
Ecco un programma Java che utilizza l'aritmetica di precisione arbitraria per eseguire il sam e calcolo. Si noti che converte il doppio valore più vicino a 0,1 in un BigDecimal - quel valore è 0.1000000000000000055511151231257827021181583404541015625. (In altre parole, il risultato esatto del calcolo è non 11 comunque.)
import java.math.*;
public class Test
{
public static void main(String[] args)
{
BigDecimal c = new BigDecimal(0.1d);
BigDecimal a = new BigDecimal(1d);
BigDecimal b = new BigDecimal(2d);
BigDecimal result = b.subtract(a)
.add(c)
.divide(c, 40, RoundingMode.FLOOR);
System.out.println(result);
}
}
Ecco il risultato:
10.9999999999999994448884876874217606030632
In altre parole, questo è corretto per circa 40 cifre decimali (modo può gestire più di 64 o 80 bit in virgola mobile).
Ora, prendiamo in considerazione l'aspetto di questo numero in binario. Non ho strumenti per fare facilmente la conversione, ma ancora una volta possiamo usare Java per aiutare. Supponendo un numero normalizzato, la parte "10" finisce usando tre bit (uno in meno rispetto a undici = 1011). Ciò lascia 60 bit di mantissa per una precisione estesa (80 bit) e 48 bit per una precisione doppia (64 bit).
Quindi, qual è il numero più vicino a 11 in ciascuna precisione? Anche in questo caso, usiamo Java:
import java.math.*;
public class Test
{
public static void main(String[] args)
{
BigDecimal half = new BigDecimal("0.5");
BigDecimal eleven = new BigDecimal(11);
System.out.println(eleven.subtract(half.pow(60)));
System.out.println(eleven.subtract(half.pow(48)));
}
}
Risultati:
10.999999999999999999132638262011596452794037759304046630859375
10.999999999999996447286321199499070644378662109375
Così, i tre numeri che abbiamo sono:
Correct value: 10.999999999999999444888487687421760603063...
11-2^(-60): 10.999999999999999999132638262011596452794037759304046630859375
11-2^(-48): 10.999999999999996447286321199499070644378662109375
Ora calcolare il valore più vicino a quella corretta per ogni precisione - per una precisione estesa, è inferiore a 11. Arrotondare ciascuno di questi valori su un valore lungo, e si finisce con 10 e 11 rispettivamente.
Speriamo che questo sia abbastanza prove per convincere i dubbiosi;)
sono gli stessi (entrambi 11) sul mio sistema? –
con cosa stai compilando questo? – Joseph
Solo per divertimento, prova a fare una variabile locale e vedere se questo cambia le cose. –