Java: A máquina dupla epsilon não é o menor x, de modo que 1 + x! = 1?

Estou tentando determinar odouble epsilon máquina em Java, usando a definição de ser o menor representáveldouble valorx de tal modo que1.0 + x != 1.0, assim como em C / C ++. De acordo com a wikipedia, esta máquina epsilon é igual a2^-52 (com 52 sendo o número dedouble bits de mantissa - 1).

Minha implementação usa oMath.ulp() função:

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

e os resultados são o que eu esperava:

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

Por enquanto, tudo bem. No entanto, se eu verificar se o dadoeps é de fato omenor x de tal modo que1.0 + x != 1.0, parece haver um menor, também conhecido comoanterior double valor de acordo comMath.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));

Qual produz:

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

Como vemos, temos um epsilon menor que o da máquina, que, adicionado a 1, não produz 1, em contradição com a definição.

Então, o que há de errado com o valor geralmente aceito para a máquina epsilon de acordo com esta definição? Ou eu perdi alguma coisa? Suspeito de outro aspecto esotérico da matemática de ponto flutuante, mas não consigo ver onde errei ...

EDITAR: Graças aos comentadores, finalmente consegui. Na verdade, usei a definição errada!eps = Math.ulp(1.0) calcula a distância até o menor dobro representável>1.0, mas - e esse é o ponto - queeps énão o menorx com1.0 + x != 1.0, mas sim sobreduas vezes esse valor: Adicionando1.0 + Math.nextAfter(eps/2) é arredondadoacima para1.0 + eps.

questionAnswers(2)

yourAnswerToTheQuestion