Джава:Добавление Double.MIN_NORMAL к двойному числу не меняет число.
-
21-12-2019 - |
Вопрос
Я думал, что MIN_NORMAL — это значение, которое можно добавить к «обычному» двойному значению, и число изменится.Например.добавьте Double.MIN_NORMAL к 0,1d, и вы получите значение, отличное от 0,1d, однако мое понимание неверно:
public static void test(double val) {
if (val == (val - Double.MIN_NORMAL*1e50d))
System.out.printf("val == (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
else
System.out.printf("val != (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
}
Что производит:
test(0.0d);
> val != (val - Double.MIN_NORMAL*1e50d) for val=0.00000000000000000000
test(1.0d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=1.00000000000000000000
test(0.1d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=0.10000000000000000000
Кто-нибудь, пожалуйста, объясните, что здесь противоречит моей логике: даже если я добавлю MIN_NORMAL раз 1e50d, я все равно получу то же число.
Я проверил двоичные представления и обнаружил, что 1 * Double.MIN_NORMAL отличается от 2 * Double.MIN_NORMAL, но вычитание их из чего-либо, кроме нуля, не меняет исходное число.
Решение
MIN_NORMAL
является, как говорит Javadoc, лишь наименьшим нормализованным double
ценить.Но это не значит, что это что-то вроде 1
для int
с:Для значений с плавающей запятой просто существует нет стандартный «eps», который вы можете добавить, чтобы перейти к следующему представимому значению — «eps» всегда зависит от показателя степени данного значения с плавающей запятой.Вот почему их называют плавающий баллы, в конце концов :)
Однако Java 1.6+ обеспечивает Math.nextAfter()
который возвращает для любого заданного double
, следующий или предыдущий представимый double
.
В старых версиях Java вы всегда можете возиться с Double.doubleToLongBits()
, увеличивая или уменьшая его результат и конвертируя обратно на Double.longBitsToDouble()
;это дает вам следующую или предыдущую репрезентативную величину double
ценить -- в большинстве случаев:есть несколько особых случаев (NaN, бесконечные значения), поэтому новичкам с плавающей запятой это не рекомендуется :)
Другие советы
Двойной имеет ограниченную точность.Min_normal 2e-1022.Он будет отброшен, если число вы не добавите его, также в балкете 2E-1000.