0

I learned this from the Java documentation

It basically says that:

Returns the floating-point value adjacent to d in the direction of positive infinity.

and especially:

If the argument is zero, the result is Double.MIN_VALUE

With this logic:

Math.nextUp(double x) - x should always be Double.MIN_VALUE.

So I tested it out:

double d_up = Math.nextUp(0);
System.out.println(d_up);                        // 1.401298464324817E-45
System.out.println(d_up == Double.MIN_VALUE);    // false
System.out.println(Double.MIN_VALUE);            // 4.9E-324

and it doesn't even work with zero.

Why does Math.nextUp(double x) not equal x + Double.MIN_VALUE?

RaminS
  • 2,208
  • 4
  • 22
  • 30
jxie0755
  • 1,682
  • 1
  • 16
  • 35

2 Answers2

4

Try this:

double d_up = Math.nextUp(0d); // see the little `d` there :)

Or this, it works as well:

double d_up = Math.nextUp(0.0); // `0.0` is a `double` literal

You need to pass a double for the advertised contract to work. Now your test works!

4.9E-324
true
4.9E-324

Just to be clear, you were passing a float before, so this was the method that got executed:

public static float nextUp​(float f)

... And naturally, that one returns Float.MIN_VALUE when 0 (an int) is passed as a parameter, because it gets automatically casted to a float. Bottom line: mind your types, make sure to cast to the right one.

Regarding the last part of your question, there's no reason why this equation should work: Math.nextUp(x) - x == Double.MIN_VALUE. double numbers are not evenly spaced, the "distance" between any two numbers is not necessarily Double.MIN_VALUE.

This is related to the fact that decimal values in a computer cannot be represented exactly, it's all an approximation that depends on the number of bits used to represent them, and that's a finite quantity - and between any two real numbers there's an infinite number of reals.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 1
    Or use `0.0` as a `double` literal. – rgettman Feb 14 '19 at 21:33
  • But what about `Math.nextUp(double x) - double x == Double.MIN_VALUE`? It doesn't seem so, only worked for 0.0 – jxie0755 Feb 14 '19 at 21:33
  • @Code_Control_jxie0755 I don't understand _why_ that should work, the contract of the method says that it just returns the next adjacent value to "the right", why the difference w.r.t. the original value should be the `MIN_VALUE`?. It'll be a small number for sure, but not zero. The "distance" between `double` values is not a fixed, constant quantity. – Óscar López Feb 14 '19 at 21:45
  • But why wouldn't the next adjacent value be the `value + Double.MIN_VALUE`? The minimum value of Double offers the minimum addition to another double value. Is that logic so wrong? – jxie0755 Feb 14 '19 at 21:49
  • Or, basically, can you describe what does adjacent mean? – jxie0755 Feb 14 '19 at 21:51
  • It is wrong, because floating point numbers are weird in computers. – RaminS Feb 14 '19 at 21:52
  • 1
    @Code_Control_jxie0755 Doubles are not evenly spaced out. The larger their magnitude, the further apart they are spaced. – khelwood Feb 14 '19 at 21:52
  • 1
    Think of it this way: *"Why would this method exist if it was just incrementing by `Float.MIN_VALUE`?"* – RaminS Feb 14 '19 at 21:54
  • @Gendarme There could be many reasons, for example, simplify the code. Again, I am not arguing with you. I just don't understand. Because apparently another double value could exist between `value` and `Math.nextUp(value)`, so how can you claim them being adjacent. – jxie0755 Feb 14 '19 at 22:06
  • Because `x + Float.MIN_VALUE` itself doesn't exist. That's the issue here (probably); not that there's another value in between (although that could also be the case, I suppose). Floating point arithmethics isn't your normal mathematics. You never use floating points for exact values; that's what [`BigDecimal`](https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html) is for. See [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). – RaminS Feb 14 '19 at 22:10
2

The floating-point numbers are similar to this: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500,…

“Adjacent” means two numbers are next to each other in this list. For numbers in this list, Math.nextup(x) - x may produce 1, 10, or 100, depending on where in the list x is.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312