ArithmeticException thrown in Java - java

In Java, (Number/0) throws an ArithmeticException while (Number/0.0) = Infinity.
Why does this happen?

Because IEEE-754 floating point numbers have a representation for infinity, whereas integers don't.
In other words, every bit pattern in int represents a normal integer; floating point values are rather more complicated with +/- infinity, "not a number" (NaN) values, normalized values, subnormal values etc.

From here
The IEEE floating-point standard, supported by almost all modern processors, specifies that every floating point arithmetic operation, including division by zero, has a well-defined result. The standard supports signed zero, as well as infinity and NaN (not a number). There are two zeroes, +0 (positive zero) and −0 (negative zero) and this removes any ambiguity when dividing. In IEEE 754 arithmetic, a ÷ +0 is positive infinity when a is positive, negative infinity when a is negative, and NaN when a = ±0. The infinity signs change when dividing by −0 instead.
Integer division by zero is usually handled differently from floating point since there is no integer representation for the result. Some processors generate an exception when an attempt is made to divide an integer by zero, although others will simply continue and generate an incorrect result for the division. The result depends on how division is implemented, and can either be zero, or sometimes the largest possible integer.

Also you can check the JLS which says:
15.17.2 Division Operator
On the other hand, if the value of the divisor in an integer division is 0, then
an ArithmeticException is thrown.
The result of a floating-point division is determined by the specification of
IEEE arithmetic:
If the result is not NaN, the sign of the result is positive if both operands have
the same sign, negative if the operands have different signs.
Division of a nonzero finite value by a zero results in a signed infinity.
The sign is determined by the rule stated above.

Related

Is Java floating arithmetic division always within 1 ULP of the true result?

Is Java's floating arithmetic division always within 1 ULP of the true result? I read that CPUs sometimes do floating-point division a/b by doing a * 1/b. However, 1/b may be off by 1 ULP, and multiplication adds up to 1 ULP of error. Doesn't this mean that the final error could be 2 ULPs?
This doesn't sound right to me, because I know there are many methods in the Math class that are within 1 ULP of the true result (such as Math.pow), so I don't think something as simple as division would be less accurate.
https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.2.4 contains Java's specifications on this. The relevant clause is probably this one:
The Java programming language requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision. Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one with its least significant bit zero is chosen. This is the IEEE 754 standard's default rounding mode known as round to nearest.
I read this as 1/2 ULP precision: the two nearest values are one ulp apart, and Java chooses "the representable value nearest to the infinitely precise result," i.e. the closer one, which must be within 1/2 ULP.

Why is 8099.99975f != 8100f?

Edit: I know floating point arithmetic is not exact. And the arithmetic isn't even my problem. The addition gives the result I expected. 8099.99975f doesn't.
So I have this little program:
public class Test {
public static void main(String[] args) {
System.out.println(8099.99975f); // 8099.9995
System.out.println(8099.9995f + 0.00025f); // 8100.0
System.out.println(8100f == 8099.99975f); // false
System.out.println(8099.9995f + 0.00025f == 8099.99975f); // false
// I know comparing floats with == can be troublesome
// but here they really should be equal in every bit.
}
}
I wrote it to check if 8099.99975 is rounded to 8100 when written as an IEEE 754 single precision float. To my surprise Java converts it to 8099.9995 when written as a float literal (8099.99975f). I checked my calculations and the IEEE standard again but couldn't find any mistakes. 8100 is just as far away from 8099.99975 as 8099.9995 but the last bit of 8100 is 0 which should make it the right representation.
So I checked the Java language spec to see if I missed something. After a quick search I found two things:
The Java programming language requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision. Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one with its least significant bit zero is chosen.
The Java programming language uses round toward zero when converting a floating value to an integer [...].
I noticed here that nothing was said about float literals. So I thought that float literals maybe are just doubles which when cast to float are rounded to zero similarly to the float to int casting. That would explain why 8099.99975f was rounded to zero.
I wrote the little program you can see above to check my theory and indeed found that when adding two float literals that should result in 8100 the correct float is computed. (Note here that 8099.9995 and 0.00025 can be represented exactly as single floats so there's no rounding that could lead to a different result) This confused me since it didn't make much sense to me that float literals and computed floats behaved differently so I dug around in the language spec some more and found this:
A floating-point literal is of type float if it is suffixed with an ASCII letter F or f [...]. The elements of the types float [...] are those values that can be represented using the IEEE 754 32-bit single-precision [...] binary floating-point formats.
This ultimately states that the literal should be rounded according to the IEEE standard which in this case is to 8100. So why is it 8099.9995?
The key point to realise is that the value of a floating point number can be worked out in two different ways, that aren't in general equal.
There's the value that the bits in the floating point number give the exact binary representation of.
There's the "decimal display value" of a floating point number, which is the number with the least decimal places that is closer to that floating point number than any other number.
To understand the difference, consider the number whose exponent is 10001011 and whose significand is 1.11111010001111111111111. This is the exact binary representation of 8099.99951171875. But the decimal value 8099.9995 has fewer decimal places, and is closer to this floating point number than to any other floating point number. Therefore, 8099.9995 is the value that will be displayed when you print out that number.
Note that this particular floating point number is the next lowest one after 8100.
Now consider 8099.99975. It's slightly closer to 8099.99951171875 than it is to 8100. Therefore, to represent it in single precision floating point, Java will pick the floating point number which is the exact binary representation of 8099.99951171875. If you try to print it, you'll see 8099.9995.
Lastly, when you do 8099.9995 + 0.00025 in single precision floating point, the numbers involved are the exact binary representations of 8099.99951171875 and 0.0002499999827705323696136474609375. But because the latter is slightly more than 1/2^12, the result of addition will be closer to 8100 than to 8099.99951171875, and so it will be rounded up, not down at the end, making it 8100.
The decimal value 8099.99975 has nine significant digits. This is more than can be represented exactly in a float. If you use the floating point analysis tool at CUNY you'll see that the binary representation closest to 8099.9995 is 45FD1FFF. When you attempt to add 0.00025 you are suffering a "loss of significance". In order not to lose significant (left-hand) digits of the larger number, the significand of the smaller has to be shifted right to match the scale (exponent) of the larger. When this happens, its value becomes ZERO as it shifts off the right end of the register.
Decimal Exponent Significand
--------- -------------- -------------------------
8099.9995 10001011 (+12) 1.11111010001111111111111
0.00025 01110011 (-12) 1.00000110001001001101111
To line these up for addition, the second one has to shift right 24 bits, but there are only 23 bits in the significand of a single-precision float. The significand disappears, leaving zero, so the addition has no effect.
If you want this to work, switch to double-precision arithmetic.

multipilcation of float value by -1 in java

Why I am getting -0.0 when 0.0 multiplied by -1???
I have taken 0.0 as float
sign=-1;
float output=0.0;
JOptionPane.showmessagedialog(null,0.0*sign);
the output shown in -0.0 instead of 0
This is an answer taken from http://www.javawebtips.com/154041/
"-0.0" Is produced when a floating-point operation results in a negative floating-point number so close to 0 that cannot be represented normally.
-2.0 / Float.POSITIVE_INFINITY -> -0.0
"-0.0" Is numerically identical to "0.0". However, some operations involving "-0.0" are different than the same operation with "0.0".
(-0.0) == 0.0 -> true
2.0 / (0.0) - Infinity
2.0 / (-0.0) ->-Infinity
Floating point values have both positive and negative zero. It may seem quirky, but there's a good reason for it (given the representational limits of floating point numbers).
You might consider casting your result to an int if you would really like the answer to just be 0.
The zeros in Java floating point do not just represent the real number zero. They are used to represent every number whose absolute magnitude is too small to be represented as a non-zero number, every underflow result.
Similarly, the infinities represent not just the result of division by zero, but every result whose absolute magnitude is too big to be represented as a finite number, every overflow result.
Making zero signed permits distinction between positive underflow results and negative underflow results, including, as already stated in another answer, getting the correct infinity on division of a non-zero number by an underflow result.

How can a primitive float value be -0.0? What does that mean?

How come a primitive float value can be -0.0? What does that mean?
Can I cancel that feature?
When I have:
float fl;
Then fl == -0.0 returns true and so does fl == 0. But when I print it, it prints -0.0.
Because Java uses the IEEE Standard for Floating-Point Arithmetic (IEEE 754) which defines -0.0 and when it should be used.
The smallest number representable has no 1 bit in the subnormal significand and is called the positive or negative zero as determined by the sign. It actually represents a rounding to zero of numbers in the range between zero and the smallest representable non-zero number of the same sign, which is why it has a sign, and why its reciprocal +Inf or -Inf also has a sign.
You can get around your specific problem by adding 0.0
e.g.
Double.toString(value + 0.0);
See: Java Floating-Point Number Intricacies
Operations Involving Negative Zero
...
(-0.0) + 0.0 -> 0.0
-
"-0.0" is produced when a floating-point operation results in a negative floating-point number so close to 0 that it cannot be represented normally.
how come a primitive float value can be -0.0?
floating point numbers are stored in memory using the IEEE 754 standard meaning that there could be rounding errors. You could never be able to store a floating point number of infinite precision with finite resources.
You should never test if a floating point number == to some other, i.e. never write code like this:
if (a == b)
where a and b are floats. Due to rounding errors those two numbers might be stored as different values in memory.
You should define a precision you want to work with:
private final static double EPSILON = 0.00001;
and then test against the precision you need
if (Math.abs(a - b) < epsilon)
So in your case if you want to test that a floating point number equals to zero in the given precision:
if (Math.abs(a) < epsilon)
And if you want to format the numbers when outputting them in the GUI you may take a look at the following article and the NumberFormat class.
The floating point type in Java is described in the JLS: 4.2.3 Floating-Point Types, Formats, and Values.
It talks about these special values:
(...) Each of the four value sets includes not only the finite nonzero values that are ascribed to it above, but also NaN values and the four values positive zero, negative zero, positive infinity, and negative infinity. (...)
And has some important notes about them:
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.
You can't "cancel" that feature, it's part of how the floats work.
For more about negative zero, have a look at the Signed zero Wikipedia entry.
If you want to check what "kind" of zero you have, you can use the fact that:
(new Float(0.0)).equals(new Float(-0.0))
is false (but indeed, 0.0 == -0.0).
Have a look here for more of this: Java Floating-Point Number Intricacies.
From wikipedia
The IEEE 754 standard for floating point arithmetic (presently used by
most computers and programming languages that support floating point
numbers) requires both +0 and −0. The zeroes can be considered as a
variant of the extended real number line such that 1/−0 = −∞ and 1/+0
= +∞, division by zero is only undefined for ±0/±0 and ±∞/±∞.
I don't think you can or need to cancel that feature. You must not compare floating point numbers with == because of precision errors anyway.
A good article on how float point numbers are managed in java / computers.
http://www.artima.com/underthehood/floating.html
btw: it is real pain in computers when 2.0 - 1.0 could produce 0.999999999999 that is not equal to1.0 :). That can be especially easy stumbled upon in javascript form validations.

Why does the use of integer variables throw an exception?

I have come across with the following two codes. Why does it not throw an exception for floating point where as in other case it will throw a runtime exception.
class FloatingPoint
{
public static void main(String [] args)
{
float a=1000f;
float b=a/0;
System.out.println("b=" +b);
}
}
OUTPUT:b=Infinity.
If I try with int values then it will throw a runtime exception.
Why is it like this?
The short answer
Integral types (JLS 4.2.1) are categorically different from floating point types (JLS 4.2.3). There may be similarities in behavior and operations, but there are also characteristically distinguishing differences such that confusing the two can lead to many pitfalls.
The difference in behavior upon division by zero is just one of these differences. Thus, the short answer is that Java behaves this way because the language says so.
On integral and floating point values
The values of the integral types are integers in the following ranges:
byte: from -128 to 127, inclusive, i.e. [-27, 27-1]
short: from -32768 to 32767, inclusive, i.e. [-215, 215-1]
int: from -2147483648 to 2147483647, inclusive, i.e. [-231, 231-1]
long: from -9223372036854775808 to 9223372036854775807, inclusive, i.e. [-263, 263-1]
char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535, i.e. [0, 216-1]
The floating-point types are float and double, which are conceptually associated with the single-precision 32-bit and double-precision 64-bit format IEEE 754 values and operations.
Their values are ordered as follows, from smallest to greatest:
negative infinity,
negative finite nonzero values,
positive and negative zero (i.e. 0.0 == -0.0),
positive finite nonzero values, and
positive infinity.
Additionally, there are special Not-a-Number (NaN) values, which are unordered. This means that if either (or both!) operand is NaN:
numerical comparison operators <, <=, >, and >= return false
numerical equality operator == returns false
numerical inequality operator != returns true
In particular, x != x is true if and only if x is NaN.
For e.g. double, the infinities and NaN can be referred to as:
Double.POSITIVE_INFINITY
Double.NEGATIVE_INFINITY
Double.NaN, testable with helper method boolean isNaN(double)
The situation is analogous with float and Float.
On when exceptions may be thrown
Numerical operations may only throw an Exception in these cases:
NullPointerException, if unboxing conversion of a null reference is required
ArithmeticException, if the right hand side is zero for integer divide/remainder operations
OutOfMemoryError, if boxing conversion is required and there is not sufficient memory
They are ordered by importance, with regards to being common source for pitfalls. Generally speaking:
Be especially careful with box types, as just like all other reference types, they may be null
Be especially careful with the right hand side of an integer division/remainder operations
Arithmetic overflow/underflow DOES NOT cause an exception to be thrown
Loss of precision DOES NOT cause an exception to be thrown
A mathematically indefinite floating point operation DOES NOT cause an exception to be thrown
On division by zero
For integer operation:
Division and remainder operations throws ArithmeticException if the right hand side is zero
For floating point operation:
If the left operand is NaN or 0, the result is NaN.
If the operation is division, it overflows and the result is a signed infinity
If the operation is remainder, the result is NaN
The general rule for all floating point operation is as follows:
An operation that overflows produces a signed infinity.
An operation that underflows produces a denormalized value or a signed zero.
An operation that has no mathematically definite result produces NaN.
All numeric operations with NaN as an operand produce NaN as a result.
Appendix
There are still many issues not covered by this already long answer, but readers are encouraged to browse related questions and referenced materials.
Related questions
What do these three special floating-point values mean: positive infinity, negative infinity, NaN?
In Java what does NaN mean.
When can Java produce a NaN (with specific code question)
Why does (360 / 24) / 60 = 0 … in Java (distinguish integer vs floating point operations!)
Why null == 0 throws NullPointerException in Java? (beware the danger of boxed primitives!)
Is 1/0 a legal Java expression? (absolutely!!!)
Because floats actually have a representation for the "number" you're trying to calculate. So it uses that. An integer has no such representation.
Java (mostly) follows IEEE754 for its floating point support, see here for more details.
It is because integer arithmetic always wraps it's result except for the case of (Division/Remainder By Zero).
In case of float, when there is an overflow or underflow, the wrapping goes to 0, infinity or NaN.
During the overflow, it gives infinity and during underflow, it gives 0.
Again there are positive & negative overflow/underflow.
Try:
float a = -1000;
float b = a/0;
System.out.println("b=" +b);
This gives a negative overflow
Output
b=-Infinity
Similarly positive underflow will result in 0 and negative underflow in -0.
Certain operations can also result in returning a NaN(Not a Number) by float/double.
For eg:
float a = -1000;
double b = Math.sqrt(a);
System.out.println("b=" +b);
Output
b=NaN
It's a programming and math standard for representing / by zero values. float has support for representing such values in JAVA. int (integer) data type doesn't have way to represent same in JAVA.
Check :
http://en.wikipedia.org/wiki/Division_by_zero
http://www.math.utah.edu/~pa/math/0by0.html

Categories

Resources