Smallest epsilon so that comparison result change - java

What is the smallest float value A so that (x < x + A) == true?
I tried with Float.MIN_VALUE but surprisingly(? [1]) it doesn't work (except for values of 0.)
Knowing how the IEEE 754 standard stores float values, I could just add 1 to the mantissa of the float in question, but this seams really hackish. I don't want to put byte arrays and bit operations in my code for such a trivial matter, especially with Java. In addition if I simply add 1 to the Float.floatToIntBits() and the mantissa is all 1, it will increase the exponent by 1 and set the mantissa to 0. I don't want to implements all the handling of this cases if it is not necessary.
Isn't there some sort of function (hopefully build-in) that given the float x, it returns the smallest float A such that (x < x + A) == true?
If there isn't, what would be the cleanest way to implement it?
I'm using this because of how I'm iterating over a line of vertices
// return the next vertices strictly at the left of pNewX
float otherLeftX = pOppositeToCurrentCave.leftVertexTo(pNewX);
// we add MIN_VALUE so that the next call to leftVertexTo will return the same vertex returned by leftVertexTo(pNewX)
otherLeftX += Float.MIN_VALUE;
while(otherLeftX >= 0 && pOppositeToCurrentCave.hasLeftVertexTo(otherLeftX)) {
otherLeftX = pOppositeToCurrentCave.leftVertexTo(otherLeftX);
//stuff
}
Right now because of this problem the first vertex is always skipped because the second call to leftVertexTo(otherLeftX) doesn't return the same value it returned on the first call
[1] Not so surprising. I happened to realize after I noticed the problem that since the gap between floats is relative, for whatever number != 0 the MIN_VALUE is so small that it will be truncated and (x = x + FLOAT.MIN_VALUE) == true

You can try Math.nextUp(x)
Here is the doc:
Returns the floating-point value adjacent to f in the direction of positive infinity. This method is semantically equivalent to nextAfter(f, Float.POSITIVE_INFINITY); however, a nextUp implementation may run faster than its equivalent nextAfter call.
Special Cases:
If the argument is NaN, the result is NaN.
If the argument is positive infinity, the result is positive infinity.
If the argument is zero, the result is Float.MIN_VALUE
Parameters:
f - starting floating-point value
Returns:
The adjacent floating-point value closer to positive infinity.

Related

Problem with how does loops and Math.abs work [duplicate]

This code:
System.out.println(Math.abs(Integer.MIN_VALUE));
Returns -2147483648
Should it not return the absolute value as 2147483648 ?
Integer.MIN_VALUE is -2147483648, but the highest value a 32 bit integer can contain is +2147483647. Attempting to represent +2147483648 in a 32 bit int will effectively "roll over" to -2147483648. This is because, when using signed integers, the two's complement binary representations of +2147483648 and -2147483648 are identical. This is not a problem, however, as +2147483648 is considered out of range.
For a little more reading on this matter, you might want to check out the Wikipedia article on Two's complement.
The behaviour you point out is indeed, counter-intuitive. However, this behaviour is the one specified by the javadoc for Math.abs(int):
If the argument is not negative, the argument is returned.
If the argument is negative, the negation of the argument is returned.
That is, Math.abs(int) should behave like the following Java code:
public static int abs(int x){
if (x >= 0) {
return x;
}
return -x;
}
That is, in the negative case, -x.
According to the JLS section 15.15.4, the -x is equal to (~x)+1, where ~ is the bitwise complement operator.
To check whether this sounds right, let's take -1 as example.
The integer value -1 is can be noted as 0xFFFFFFFF in hexadecimal in Java (check this out with a println or any other method). Taking -(-1) thus gives:
-(-1) = (~(0xFFFFFFFF)) + 1 = 0x00000000 + 1 = 0x00000001 = 1
So, it works.
Let us try now with Integer.MIN_VALUE . Knowing that the lowest integer can be represented by 0x80000000, that is, the first bit set to 1 and the 31 remaining bits set to 0, we have:
-(Integer.MIN_VALUE) = (~(0x80000000)) + 1 = 0x7FFFFFFF + 1
= 0x80000000 = Integer.MIN_VALUE
And this is why Math.abs(Integer.MIN_VALUE) returns Integer.MIN_VALUE. Also note that 0x7FFFFFFF is Integer.MAX_VALUE.
That said, how can we avoid problems due to this counter-intuitive return value in the future?
We could, as pointed out by #Bombe, cast our ints to long before. We, however, must either
cast them back into ints, which does not work because
Integer.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE).
Or continue with longs somehow hoping that we'll never call Math.abs(long) with a value equal to Long.MIN_VALUE, since we also have Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE.
We can use BigIntegers everywhere, because BigInteger.abs() does indeed always return a positive value. This is a good alternative, though a bit slower than manipulating raw integer types.
We can write our own wrapper for Math.abs(int), like this:
/**
* Fail-fast wrapper for {#link Math#abs(int)}
* #param x
* #return the absolute value of x
* #throws ArithmeticException when a negative value would have been returned by {#link Math#abs(int)}
*/
public static int abs(int x) throws ArithmeticException {
if (x == Integer.MIN_VALUE) {
// fail instead of returning Integer.MAX_VALUE
// to prevent the occurrence of incorrect results in later computations
throw new ArithmeticException("Math.abs(Integer.MIN_VALUE)");
}
return Math.abs(x);
}
Use a integer bitwise AND to clear the high bit, ensuring that the result is non-negative: int positive = value & Integer.MAX_VALUE (essentially overflowing from Integer.MAX_VALUE to 0 instead of Integer.MIN_VALUE)
As a final note, this problem seems to be known for some time. See for example this entry about the corresponding findbugs rule.
Here is what Java doc says for Math.abs() in javadoc:
Note that if the argument is equal to
the value of Integer.MIN_VALUE, the
most negative representable int value,
the result is that same value, which
is negative.
To see the result that you are expecting, cast Integer.MIN_VALUE to long:
System.out.println(Math.abs((long) Integer.MIN_VALUE));
There is a fix to this in Java 15 will be a method to int and long. They will be present on the classes
java.lang.Math and java.lang.StrictMath
The methods.
public static int absExact(int a)
public static long absExact(long a)
If you pass
Integer.MIN_VALUE
OR
Long.MIN_VALUE
A Exception is thrown.
https://bugs.openjdk.java.net/browse/JDK-8241805
I would like to see if either Long.MIN_VALUE or Integer.MIN_VALUE is passed a positive value would be return and not a exception but.
2147483648 cannot be stored in an integer in java, its binary representation is the same as -2147483648.
But (int) 2147483648L == -2147483648 There is one negative number which has no positive equivalent so there is not positive value for it. You will see the same behaviour with Long.MAX_VALUE.
Math.abs doesn't work all the time with big numbers I use this little code logic that I learnt when I was 7 years old!
if(Num < 0){
Num = -(Num);
}

Java If a number is -0

If have this code:
double sin = Math.sin(angle*rad);
double cos = Math.cos(angle*rad);
double tan = Math.tan(angle*rad);
It returns the triangle function for a specified angle. However for degrees of angle, like 90, -0.00000 is returned. So when these values are printed out, -0 just looks weird. How would -0 be tested for in an if statement?
I have tried with this code:
if (tan==0) { s.o.p(tan); }
and it doesn't run.
Just take the absolute value on the variable when you compare it with zero. You will likely need to cover a range since it's not always likely to be exactly 0.0.
if (Math.abs(tan) <= threshold) { ... }
Where you set threshold to a small enough value to cover what you consider is close enough to 0.
Edit: Added threshold/epsilon value in comparison - thanks Ben
You can check for negative zero by dividing 1 by your value. This will yield Double.POSITIVE_INFINITY for a positive zero and Double.NEGATIVE_INFINITY for a negative zero:
if (1.0 / value == Double.NEGATIVE_INFINITY) {
// Value was a negative zero
}

Double divide by zero: Why is the result inconsistent?

Why are the results of:
double a = 0.0/0.0;
double b = 0/0.0;
= NaN
But the results of for example:
double e = 0.1/0.0;
double e = 12.0/0.0;
double f = 1.0/0.0;
= Infinity
I understand that double or float divisions are somehow a little bit different. I am pretty happy with the resulting NaN because the result is not defined when something is divided by zero. But why they defined that the result of something greater than zero divided by zero is Infitity? Has this something todo with the method they use to perform the division of floating points?
JLS 15.17.2 clearly states that
Division of a zero by a zero results in NaN; division of zero by any other finite value results in a signed zero. The sign is determined by the rule stated above.
Division of a nonzero finite value by a zero results in a signed infinity. The sign is determined by the rule stated above.
The JLS also says about the difference between these constants in operations.
If either operand is NaN, the result is NaN.
Division of an infinity by an infinity results in NaN.
Division of an infinity by a finite value results in a signed infinity. The sign is determined by the rule stated above.
Not inconsistent at all.
According to math definition following operations result in an undetermined result and that is what NAN represent!
Following undetermined result can be:
0/0,
∞/∞,
0*∞,
∞-∞,
0^0,
1^∞,
0^∞
java match almost all of them (except ∞^0 and 0^0)
// 0/0
double a = 0.0 / 0.0;
System.out.println(a);
// ∞/∞
a = Double.POSITIVE_INFINITY / Double.POSITIVE_INFINITY;
System.out.println(a);
// 0*∞
a = 0 * Double.POSITIVE_INFINITY;
System.out.println(a);
// ∞-∞
a = Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY;
System.out.println(a);
// 0^0
a = Math.pow(0, 0);
System.out.println(a);
// 1^∞
a = Math.pow(1, Double.POSITIVE_INFINITY);
System.out.println(a);
// ∞^0
a = Math.pow(Double.POSITIVE_INFINITY, 0);
System.out.println(a);
There are other answers that specify that this is in the standard and therefore "expected" behavior. You seem to want to know why the standard is like that. I would guess that the reason is that some expressions have well-defined limits (as in calculus) and some do not even have a limit. The ones with a well-defined limit get a signed infinity (since that is the limit). The ones like 0/0 get NaN because there is no limit there. (The limit from the left is negative infinity and the limit from the right is positive infinity.) In all cases, when I say "limit", I mean limit of n/x as x -> 0, where n is the fixed numerator.

Java: Adding Double.MIN_NORMAL to a double doesn't change the number

I thought that MIN_NORMAL was a value that you could add to a "normal" double and the number will change. E.g. add Double.MIN_NORMAL to 0.1d and you get a value different from 0.1d, however my understanding is wrong:
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);
}
Which produces:
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
Somebody pls explain what's going against my logic here, that even if I add MIN_NORMAL times 1e50d, I still get the same number.
I checked binary representations and 1 * Double.MIN_NORMAL is different from 2 * Double.MIN_NORMAL, but subtracting those from anything except zero does not change the original number.
MIN_NORMAL is, as the Javadoc says, only the smallest normalized double value. But that doesn't mean it is something like 1 for ints: For floating-point point values, there simply is no standard "eps" you can add to change to the next representable value -- the "eps" always depends on the exponent of the given floating-point value. That's why they're called floating points, in the end :)
However, Java 1.6+ provides Math.nextAfter() which returns, for any given double, the next or previous representable double.
On older Java versions, you can always mess around with Double.doubleToLongBits(), incrementing or decrementing its result, and converting back by Double.longBitsToDouble(); this gets you the next or previous representable double value -- in most cases: there are a few special cases (NaN, infinite values), so this is not recommended to floating-point newbies :)
Double has a limited precision. MIN_NORMAL is 2e-1022. It will be dropped unless the number you add it to is also in the ballpark of 2e-1000.

Floating point rounding (in java)

What is the best way of determining if a given float(or double) has no significant decimal places.
f(234.0) = true
f(34.45) = false
f(3.1322) = false
i.e. equivalent of
EQ(((int)number) * 1.0 , number)
where EQ is a given method to compare floating points and it is OK to assume that the float fits in an integer.
Math.rint(x) == x
Math.rint() returns a double, so it also works for large numbers where the long result of Math.round() overflows.
Note that this also gives true for positive and negative infinity. You can explicitly exclude them by Math.rint(x) == x && !Double.isInfinite(x).
Round the value to the nearest integer, and calculate the absolute difference to the actual value.
If that difference is less than a certain percentage of the actual value you are close "enough".
You could try something like this:
public static boolean f(double d) {
return d % 1 == 0;
}

Categories