Ответ 1
Я подозреваю, что разница заключается в преобразовании из 80-битного значения с плавающей запятой в длинное и преобразование из 80-битного значения с плавающей запятой в 64-битное, а затем преобразование в длинное.
(Причина появления 80 бит - это то, что типичная точность используется для фактической арифметики и ширины регистров с плавающей запятой.)
Предположим, что 80-битный результат - это что-то вроде 10.999999999999999 - переход от этого к длинному урожаю 10. Однако ближайшее 64-битное значение с плавающей запятой до 80-битного значения на самом деле составляет 11,0, поэтому двухэтапное преобразование заканчивается тем, что дает 11.
РЕДАКТИРОВАТЬ: дать этому немного больше веса...
Здесь программа Java, которая использует арифметику произвольной точности для выполнения одного и того же вычисления. Обратите внимание, что он преобразует двойное значение, самое близкое к 0,1, в BigDecimal - это значение равно 0,1000000000000000055511151231257827021181583404541015625. (Другими словами, точный результат вычисления не равно 11).
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);
}
}
Здесь результат:
10.9999999999999994448884876874217606030632
Другими словами, это исправление примерно до 40 десятичных цифр (может обрабатывать не более 64 или 80 бит с плавающей запятой).
Теперь рассмотрим, как выглядит это число в двоичном формате. У меня нет инструментов для простого преобразования, но мы снова можем использовать Java. Предполагая нормализованное число, часть "10" заканчивается использованием трех бит (один меньше, чем одиннадцать = 1011). Это оставляет 60 бит мантиссы для расширенной точности (80 бит) и 48 бит для двойной точности (64 бит).
Итак, что самое близкое число до 11 в каждой точности? Опять же, позвольте использовать 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)));
}
}
Результаты:
10.999999999999999999132638262011596452794037759304046630859375
10.999999999999996447286321199499070644378662109375
Итак, три числа, которые у нас есть:
Correct value: 10.999999999999999444888487687421760603063...
11-2^(-60): 10.999999999999999999132638262011596452794037759304046630859375
11-2^(-48): 10.999999999999996447286321199499070644378662109375
Теперь выведите самое близкое значение к правильному для каждой точности - для расширенной точности - менее 11. Разобьте каждое из этих значений на длинное, и вы получите соответственно 10 и 11.
Надеюсь, этого достаточно, чтобы убедить сомневающихся;)