I'm writing a Java class that tracks a fractional number, but needs to be able to increment and decrement it. Using a double for this number seems to work fine for small values, but I'm trying to figure out its limits.
I was thinking that one way of determining it might be to run a program that incremented a double and a long until they were no longer equal. However this takes too long to run.
double x = 0;
long y = 0;
while ((long)x == y)
{
x++;
y++;
}
System.out.println("X: " + x);
System.out.println("Y: " + y);
What are double's limits where you can no longer increment a value and actually add one to it? I'd think that decrementing a double would have a similar problem with negative numbers at some point.
You essentially want the largest positive number with the ulp of 1. This is the largest positive number where adding 1 will still change it.
From the Wikipedia page we can see that ulp for a normal number x between 2^e and 2^(e+1) is calculated as 2^(e-p+1), where p is the precision (number of bits in the mantissa).

For double, p is 53, so we want to find a value of e such that 2^(e-52) is 1. Obviously, e should be 52.
Then we can construct a double with the exponent 52, and the largest mantissa possible. You can write it as a long:
Double.longBitsToDouble(
0x433FFFFFFFFFFFFFL
);
Due to how doubles are represented, we need to write "433" (1075 in decimal). This is the number from which subtracting 1023 will give you the desired exponent of 52.
This is the largest number where adding 1 will still change the number. nextUp of this number will remain unchanged when you add 1:
double x = Double.longBitsToDouble(
0x433FFFFFFFFFFFFFL
);
double y = Math.nextUp(x);
System.out.println(x + 1 == x); // false
System.out.println(y + 1 == y); // true
Another way of writing x is 0x1p53 - 1 (credits to Holger in the comments), i.e. one less than the number with an exponent of 53.
The situation is symmetric for decrementing:
double x = -Double.longBitsToDouble(
0x433FFFFFFFFFFFFFL
);
double y = Math.nextDown(x);
System.out.println(x - 1 == x); // false
System.out.println(y - 1 == y); // true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With