Я думал, что 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
Кто-то pls объясняет, что идет против моей логики здесь, что, даже если я добавлю MIN_NORMAL раз 1e50d, я все равно получаю тот же номер.
Я проверил двоичные представления и 1 * Double.MIN_NORMAL отличается от 2 * Double.MIN_NORMAL, но вычитание из ничего, кроме нуля, не изменяет исходный номер.
MIN_NORMAL
, как говорит Javadoc, имеет только наименьшее нормированное double
значение. Но это не значит, что это что-то вроде 1
для int
s: для значений точки с плавающей запятой просто нет стандартного "eps", который вы можете добавить, чтобы перейти к следующему представляемому значению - "eps" всегда зависит от показателем данного значения с плавающей запятой. Вот почему их называют плавающими точками, в конце концов :)
Однако Java 1. 6+ предоставляет Math.nextAfter()
который возвращает для любого заданного double
следующего или предыдущего представляемого double
.
На старых версиях Java вы всегда можете Double.doubleToLongBits()
с Double.doubleToLongBits()
, увеличивая или уменьшая его результат и возвращая обратно Double.longBitsToDouble()
; это дает вам следующее или предыдущее представляемое double
значение - в большинстве случаев: есть несколько особых случаев (NaN, бесконечные значения), поэтому это не рекомендуется для новичков с плавающей запятой :)
Двойник имеет ограниченную точность. MIN_NORMAL - 2e-1022. Он будет удален, если только вы не добавите его, также находится на стадионе 2e-1000.
-1022
. Итак, ваш1e50d
ничто по сравнению.MIN_NORMAL
гарантированно будет иметь эффект при добавлении / вычитании из0
, но в противном случае вы не можете полагаться на то, что он будет иметь эффект. В частности, он не собирается ничего делать со сравнительно гигантскими числами, такими как1.0
или0.1
.