Java: Эпсилон с двумя машинами - это не самый маленький x такой, что 1 + x! = 1?

Я пытаюсь определитьdouble машина эпсилон в Java, используя определение его как наименьшего представимогоdouble значениеx такой, что1.0 + x != 1.0так же, как в C / C ++. Согласно википедии, эта машина эпсилон равна2^-52 (с 52 числоdouble биты мантиссы - 1).

Моя реализация используетMath.ulp() функция:

double eps = Math.ulp(1.0);
System.out.println("eps = " + eps);
System.out.println("eps == 2^-52? " + (eps == Math.pow(2, -52)));

и результаты - это то, что я ожидал:

eps = 2.220446049250313E-16
eps == 2^-52? true

Все идет нормально. Однако, если я проверю, что данныйeps действительнонаименьшее x такой, что1.0 + x != 1.0, кажется, есть меньший, иначепредыдущий double значение в соответствии сMath.nextAfter():

double epsPred = Math.nextAfter(eps, Double.NEGATIVE_INFINITY);
System.out.println("epsPred = " + epsPred);
System.out.println("epsPred < eps? " + (epsPred < eps));
System.out.println("1.0 + epsPred == 1.0? " + (1.0 + epsPred == 1.0));

Который дает:

epsPred = 2.2204460492503128E-16
epsPred < eps? true
1.0 + epsPred == 1.0? false

Как мы видим, у нас есть эпсилон меньше, чем машина, который, добавленный к 1, дает не 1, что противоречит определению.

Так что же не так с общепринятым значением для машины эпсилон согласно этому определению? Или я что-то пропустил? Я подозреваю другой эзотерический аспект математики с плавающей точкой, но я не вижу, где я ошибся ...

РЕДАКТИРОВАТЬ: Спасибо комментаторам, я наконец-то понял. Я на самом деле использовал неправильное определение!eps = Math.ulp(1.0) вычисляет расстояние до наименьшего представимого двойника>1.0, но - и в этом все дело - чтоeps являетсяне наименьшийx с1.0 + x != 1.0, а скорее одважды это значение: добавление1.0 + Math.nextAfter(eps/2) округляетсявверх в1.0 + eps.

Ответы на вопрос(2)

Ваш ответ на вопрос