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.
Related
Does Java have anything to represent infinity for every numerical data type? How is it implemented such that I can do mathematical operations with it?
E.g.
int myInf = infinity; //However it is done
myInf + 5; //returns infinity
myInf*(-1); //returns negative infinity
I have tried using very large numbers, but I want a proper, easy solution.
double supports Infinity
double inf = Double.POSITIVE_INFINITY;
System.out.println(inf + 5);
System.out.println(inf - inf); // same as Double.NaN
System.out.println(inf * -1); // same as Double.NEGATIVE_INFINITY
prints
Infinity
NaN
-Infinity
note: Infinity - Infinity is Not A Number.
I'm supposing you're using integer math for a reason. If so, you can get a result that's functionally nearly the same as POSITIVE_INFINITY by using the MAX_VALUE field of the Integer class:
Integer myInf = Integer.MAX_VALUE;
(And for NEGATIVE_INFINITY you could use MIN_VALUE.) There will of course be some functional differences, e.g., when comparing myInf to a value that happens to be MAX_VALUE: clearly this number isn't less than myInf. Also, as noted in the comments below, incrementing positive infinity will wrap you back around to negative numbers (and decrementing negative infinity will wrap you back to positive).
There's also a library that actually has fields POSITIVE_INFINITY and NEGATIVE_INFINITY, but they are really just new names for MAX_VALUE and MIN_VALUE.
To use Infinity, you can use Double which supports Infinity: -
System.out.println(Double.POSITIVE_INFINITY);
System.out.println(Double.POSITIVE_INFINITY * -1);
System.out.println(Double.NEGATIVE_INFINITY);
System.out.println(Double.POSITIVE_INFINITY - Double.NEGATIVE_INFINITY);
System.out.println(Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY);
OUTPUT: -
Infinity
-Infinity
-Infinity
Infinity
NaN
The Double and Float types have the POSITIVE_INFINITY constant.
Integer Infinity :
Integer maxNumber = Integer.MAX_VALUE
Double Infinity
Double maxNumber = Double.MAX_VALUE;
Double positiveInf = Double.POSITIVE_INFINITY;
Double negativeInf = Double.NEGATIVE_INFINITY
Float infinity
Float positiveInf = Float.POSITIVE_INFINITY;
Float negativeInf = Float.NEGATIVE_INFINITY
Float maxNumber = Float.MAX_VALUE;
I'm not sure that Java has infinity for every numerical type but for some numerical data types the answer is positive:
Float.POSITIVE_INFINITY
Float.NEGATIVE_INFINITY
or
Double.POSITIVE_INFINITY
Double.NEGATIVE_INFINITY
Also you may find useful the following article which represents some mathematical operations involving +/- infinity: Java Floating-Point Number Intricacies.
Only Double and Float type support POSITIVE_INFINITY constant.
A generic solution is to introduce a new type. It may be more involved, but it has the advantage of working for any type that doesn't define its own infinity.
If T is a type for which lteq is defined, you can define InfiniteOr<T> with lteq something like this:
class InfiniteOr with type parameter T:
field the_T of type null-or-an-actual-T
isInfinite()
return this.the_T == null
getFinite():
assert(!isInfinite());
return this.the_T
lteq(that)
if that.isInfinite()
return true
if this.isInfinite()
return false
return this.getFinite().lteq(that.getFinite())
I'll leave it to you to translate this to exact Java syntax. I hope the ideas are clear; but let me spell them out anyways.
The idea is to create a new type which has all the same values as some already existing type, plus one special value which—as far as you can tell through public methods—acts exactly the way you want infinity to act, e.g. it's greater than anything else. I'm using null to represent infinity here, since that seems the most straightforward in Java.
If you want to add arithmetic operations, decide what they should do, then implement that. It's probably simplest if you handle the infinite cases first, then reuse the existing operations on finite values of the original type.
There might or might not be a general pattern to whether or not it's beneficial to adopt a convention of handling left-hand-side infinities before right-hand-side infinities or vice versa; I can't tell without trying it out, but for less-than-or-equal (lteq) I think it's simpler to look at right-hand-side infinity first. I note that lteq is not commutative, but add and mul are; maybe that is relevant.
Note: coming up with a good definition of what should happen on infinite values is not always easy. It is for comparison, addition and multiplication, but maybe not subtraction. Also, there is a distinction between infinite cardinal and ordinal numbers which you may want to pay attention to.
For the numeric wrapper types.
e.g Double.POSITIVE_INFINITY
Hope this might help you.
Since the class Number is not final, here is an
idea, that I don't find yet in the other posts.
Namely to subclass the class Number.
This would somehow deliver an object that can be treated
as infinity for Integer, Long, Double, Float,
BigInteger and BigDecimal.
Since there are only two values, we could use the singleton pattern:
public final class Infinity extends Number {
public final static Infinity POSITIVE = new Infinity(false);
public final static Infinity NEGATIVE = new Infinity(true);
private boolean negative;
private Infinity(boolean n) {
negative = n;
}
}
Somehow I think the remaining methods intValue(), longValue()
etc.. should then be overriden to throw an exceptions. So that
the infinity value cannot be used without further precautions.
I'm a beginner in Java...
I found another implementation for the infinity in the Java documentation, for the boolean and double types.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3
Positive zero and negative zero compare equal; thus the result of the
expression 0.0==-0.0 is true and the result of 0.0>-0.0 is false. But
other operations can distinguish positive and negative zero; for
example, 1.0/0.0 has the value positive infinity, while the value of
1.0/-0.0 is negative infinity.
It looks ugly, but it works.
public class Main {
public static void main(String[] args) {
System.out.println(1.0/0.0);
System.out.println(-1.0/0.0);
}
}
I have a line of code that adds together a few doubles and it give a result of infinity, while the double are all just small but long decimals
a = -1.536709757154733E308
b = 2.102331119338414E156
c = 0.2
d = a - b + (a * c)
d = -1.536709757154733E308 - 2.102331119338414E156 + (-1.536709757154733E308 * 0.2)
d = -infinity
Does anyone know why this is happening? Any help would be much appreciated
PS it is not feasible to use Big Decimals in this code and due to the random 'a' and 'b' change on each run
Overflow is occurring. The magnitude of the result of the expression a - b + (a * c) is greater than the largest possible double, Double.MAX_VALUE, or 1.7976931348623157E308. When this occurs, the result is an infinity. Because a was negative, this results in -Infinity.
You can see this if you decrease the exponents of a and b by 1 to see what the result would be:
-1.8440517085856795E307
Increasing the exponent by 1 again in the result would yield a magnitude larger than the maximum possible magnitude.
You can still use BigDecimals.
BigDecimal a = new BigDecimal(-1.536709757154733E308);
BigDecimal b = new BigDecimal(2.102331119338414E156);
BigDecimal c = new BigDecimal(0.2);
System.out.println(a.add(b).add(a.multiply(c)));
That decimal point is deceiving you. To see how large that double value actually is, use the NumberFormat as
double d = 2.102331119338414E156;
System.out.println(NumberFormat.getNumberInstance().format(d));
Output :
2,102,331,119,338,414,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
Hence, switching to a BigDecimal should help. If you're generating the a and b values randomly, take a look at Generating random BigDecimal value from given range.
So, with the scientific notation and large numbers represented out of the way, let's look at a simplified form.
a = -1.5E308 // round down*
b = 2.1E156
c = 0.2
d = a - b + (a * c)
d = -1.5E308 - 2.1E156 + (-1.5E308 * 0.2)
d = -1.5E308 - {insignificant*} + (-0.3E308)
d = -1.8E308 // under normal math ..
.. BUT, 64-bit IEEE 754 Double's - which is the format that double is stored in - have a range of ~[-1.79E308, 1.79E308] as only so much information can be stored in 64 bits.
The result of -1.8E308 is outside of this range. Hence it is represented as (negative) Infinity.
* Note the initial round down and throwing away the insignificant value - this the result is guaranteed to be < -1.8E308, although feel free to work it out to more precision. The point is this is outside the representable range of a double.
Using a BigDecimal works because (and it doesn't matter if the input is "random") because it doesn't have this range limit.
When creating a range of numbers as follows,
float increment = 0.01f;
for (int i = 0; i < 100; i++) {
float value = i * increment;
System.out.println(value);
}
it is clear, that I will end up for some i with values like
0.049999997, which are no exact multiples of 0.01, due to rounding errors.
When I try the same with floats in the range of usual integers, I have never seen the same problem:
float increment = 1.0f; //Still a float but representing an int value
for (int i = 0; i < 100; i++) {
float value = i * increment;
System.out.println(value);
}
One could expect, that this also prints out e.g. 49.999999 instead of 50, which I never saw however.
I am wondering, whether I can rely on that for any value of i and any value of increment, as long as it represents an integer (although its type is float).
And if so, I would be interested in an explanation, why rounding errors can not happen in that case.
Integers in a certain range (about up to one million or so) can be represented exactly as a float. Therefore you don't get rounding errors when you work only with them.
This is because float is based on floating point notation.
In rude words it tries to represent your decimal number as a sum of fractions of power 2.
It means it will try to sum 1/2^n1 + 1/2^n2 + 1/2^n3 .... 1/2^nm until gets closes or exact value that you put.
For example (rude):
0.5 it will represent as 1/2
0.25 it will represent as 1/2²
0.1 it will represent as 1/2^4
but in this case it will mutiply the number by 1.600000023841858 (mantissa) and it will give a number closer but not equal to 1 (1/2^4 x 1.600000023841858 = 0,100000001
Now you can see why after some loops the value changes to nonsense values
For rich detail of how it works read floating points IEEE 754
If you want precision you should use for example a BigDecimal from Java that uses another architecture to represent decimal numbers.
Double has the same problem.
Check this tool to see the repressentation of floating point:
http://www.h-schmidt.net/FloatConverter/IEEE754.html
It doesn't really represent an integer. It's still a float that you're just attempting to add the value 1.0 to. You'll get rounding errors as soon as 1.0 underflows (whenever the exponent gets larger than zero).
The double Value increases randomly.
for(double i=-1;i<=1;i+=0.1)
{
for(double j=-1;j<=1;j+=0.1)
{
//logic
system.out.print(i);
system.out.print(j);
}
}
Here, the value comes like:
-1, -0.9, -0.8, -0.69, -0.51 ....-0.099 , 1.007 (WHY, U ARE GREATER THAN 1)
The output is not same but kind of this.
But, I want the exact values only. WHat should I do ??
You can use an integer counter, and multiply to get the double:
for(int i = -10; i <= 10; i++) {
double iDouble = 0.1 * i;
....
}
The double will still have rounding error - that is inevitable - but the rounding error will not affect the loop count.
You can't get exact values do to the limitations of doubles. They can't always represent exactly the decimal you want, and they have precision errors. In your case you may want to cast the double to an int for the double comparison, but as #alex said you shouldn't be doing this.
This is due to the way that doubles are stored in memory, they are only exact if the fractional part is a negative power of two, e.g. 0, 1/2, 1/4, etc. This is also why you should never use equality statements for doubles, but rather > and <. For exact calculations, you could use BigDecimal:
BigDecimal bigDecimal = new BigDecimal(123.45);
bigDecimal = bigDecimal.add(new BigDecimal(123.45));
System.out.println(bigDecimal.floatValue()); // prints 246.9
As said here, floating-point variables must not be used as loop counters. Limited-precision IEEE 754 floating-point types cannot represent:
all simple fractions exactly
all decimals precisely, even when the decimals can be represented in a small number of digits.
all digits of large values, meaning that incrementing a large floating-point value might not change that value within the available precision.
(...) Using floating-point loop counters can lead to unexpected behavior.
Instead, use integer loop counter and increment another variable inside this loop like this:
for (int count = 1; count <= 20; count += 1) {
double x = -1 + count * 0.1;
/* ... */
}
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.