I have code to calculate the percentage difference between 2 numbers - (oldNum - newNum) / oldNum * 100; - where both of the numbers are doubles. I expected to have to add some sort of checking / exception handling in case oldNum is 0. However, when I did a test run with values of 0.0 for both oldNum and newNum, execution continued as if nothing had happened and no error was thrown. Running this code with ints would definitely cause an arithmetic division-by-zero exception. Why does Java ignore it when it comes to doubles?
Java's float and double types, like pretty much any other language out there (and pretty much any hardware FP unit), implement the IEEE 754 standard for floating point math, which mandates division by zero to return a special "infinity" value. Throwing an exception would actually violate that standard.
Integer arithmetic (implemented as two's complement representation by Java and most other languages and hardware) is different and has no special infinity or NaN values, thus throwing exceptions is a useful behaviour there.
The result of division by zero is, mathematically speaking, undefined, which can be expressed with a float/double (as NaN - not a number), it isn't, however, wrong in any fundamental sense.
As an integer must hold a specific numerical value, an error must be thrown on division by zero when dealing with them.
When divided by zero ( 0 or 0.00 )
If you divide double by 0, JVM will show Infinity.
public static void main(String [] args){ double a=10.00; System.out.println(a/0); }
Console:
Infinity
If you divide int by 0, then JVM will throw Arithmetic Exception.
public static void main(String [] args){
int a=10;
System.out.println(a/0);
}
Console: Exception in thread "main" java.lang.ArithmeticException: / by zero
But if we divide int by 0.0, then JVM will show Infinity:
public static void main(String [] args){
int a=10;
System.out.println(a/0.0);
}
Console: Infinity
This is because JVM will automatically type cast int to double, so we get infinity instead of ArithmeticException.
The way a double is stored is quite different to an int. See http://firstclassthoughts.co.uk/java/traps/java_double_traps.html for a more detailed explanation on how Java handles double calculations. You should also read up on Floating Point numbers, in particular the concept of Not a Number (NaN).
If you're interested in learning more about floating point representation, I'd advise reading this document (Word format, sorry). It delves into the binary representation of numbers, which may be helpful to your understanding.
Though Java developers know about the double primitive type and Double class, while doing floating point arithmetic they don't pay enough attention to Double.INFINITY, NaN, -0.0 and other rules that govern the arithmetic calculations involving them.
The simple answer to this question is that it will not throw ArithmeticException and return Double.INFINITY. Also, note that the comparison x == Double.NaN always evaluates to false, even if x itself is a NaN.
To test if x is a NaN, one should use the method call Double.isNaN(x) to check if given number is NaN or not. This is very close to NULL in SQL.
It may helpful for you.
Related
SonarQube has a rule that reports a bug in the following code, stating that "floating point numbers should not be tested for equality". Generally this rule is justified, but in this case to me it seems to be a false positive. If it is so, I would like to flag it as such, rather than to work around it using constructs with Double.compare, checking intermediate results for +/-Infinity, NaN, or things like that.
public void f(double denominator)
{
if (denominator == 0.0d)
throw new IllegalArgumentException("Division by zero.");
// code that involves division by denominator ...
}
Hence the question: Does the above code throw the IllegalArgumentException if and only if division by denominator (in expressions containing doubles only) would lead to +/-Infinity or NaN intermediate values?
We should avoid test float for equality because of the behavior of representing decimals in binary.
The question you asked is essentially, does the above code work?
Depending on how f is used, specifically if you are not explicitly passing in 0.0 as the parameter and instead doing something like f((0.4-0.1)-0.3), it will not catch and divide by a decimal very CLOSE to 0.
P.S. if you want decimal precision, use BigDecimal.
I am an experienced php developer just starting to learn Java. I am following some Lynda courses at the moment and I'm still really early stages. I'm writing sample programs that ask for user input and do simple calculation and stuff.
Yesterday I came across this situation:
double result = 1 / 2;
With my caveman brain I would think result == 0.5, but no, not in Java. Apparantly 1 / 2 == 0.0. Yes, I know that if I change one of the operands to a double the result would also be a double.
This scares me actually. I can't help but think that this is very broken. It is very naive to think that an integer division results in an integer. I think it is even rarely the case.
But, as Java is very widely used and searching for 'why is java's division broken?' doesn't yield any results, I am probably wrong.
My questions are:
Why does division behave like this?
Where else can I expect to find such magic/voodoo/unexpected behaviour?
Java is a strongly typed language so you should be aware of the types of the values in expressions. If not...
1 is an int (as 2), so 1/2 is the integer division of 1 and 2, so the result is 0 as an int. Then the result is converted to a corresponding double value, so 0.0.
Integer division is different than float division, as in math (natural numbers division is different than real numbers division).
You are thinking like a PHP developer; PHP is dynamically typed language. This means that types are deduced at run-time, so a fraction cannot logically produce a whole number, thus a double (or float) is implied from the division operation.
Java, C, C++, C# and many other languages are strongly typed languages, so when an integer is divided by an integer you get an integer back, 100/50 gives me back 2, just like 100/45 gives me 2, because 100/45 is actually 2.2222..., truncate the decimal to get a whole number (integer division) and you get 2.
In a strongly typed language, if you want a result to be what you expect, you need to be explicit (or implicit), which is why having one of your parameters in your division operation be a double or float will result in floating point division (which gives back fractions).
So in Java, you could do one of the following to get a fractional number:
double result = 1.0 / 2;
double result = 1f / 2;
double result = (float)1 / 2;
Going from a loosely typed, dynamic language to a strongly typed, static language can be jarring, but there's no need to be scared. Just understand that you have to take extra care with validation beyond input, you also have to validate types.
Going from PHP to Java, you should know you can not do something like this:
$result = "2.0";
$result = "1.0" / $result;
echo $result * 3;
In PHP, this would produce the output 1.5 (since (1/2)*3 == 1.5), but in Java,
String result = "2.0";
result = "1.0" / result;
System.out.println(result * 1.5);
This will result in an error because you cannot divide a string (it's not a number).
Hope that can help.
I'm by no means a professional on this, but I think it's because of how the operators are defined to do integer arithmetic. Java uses integer division in order to compute the result because it sees that both are integers. It takes as inputs to this "division" method two ints, and the division operator is overloaded, and performs this integer division. If this were not the case, then Java would have to perform a cast in the overloaded method to a double each time, which is in essence useless if you can perform the cast prior anyways.
If you try it with c++, you will see the result is the same.
The reason is that before assigning the value to the variable, you should calculate it. The numbers you typed (1 and 2) are integers, so their memory allocation should be as integers. Then, the division should done according to integers. After that it will cast it to double, which gives 0.0.
Why does division behave like this?
Because the language specification defines it that way.
Where else can I expect to find such magic/voodoo/unexpected behaviour?
Since you're basically calling "magic/voodoo" something which is perfectly defined in the language specification, the answer is "everywhere".
So the question is actually why there was this design decision in Java. From my point of view, int division resulting in int is a perfectly sound design decision for a strongly typed language. Pure int arithmetic is used very often, so would an int division result in float or double, you'd need a lot of rounding which would not be good.
package demo;
public class ChocolatesPurchased
{
public static void main(String args[])
{
float p = 3;
float cost = 2.5f;
p *= cost;
System.out.println(p);
}
}
I was just messing around with this method to see what it does. I created a variable with value 3.14 just because it came to my mind at that instance.
double n = 3.14;
System.out.println(Math.nextUp(n));
The preceding displayed 3.1400000000000006.
Tried with 3.1400000000000001, displayed the same.
Tried with 333.33, displayed 333.33000000000004.
With many other values, it displays the appropriate value for example 73.6 results with 73.60000000000001.
What happens to the values in between 3.1400000000000000 and 3.1400000000000006? Why does it skips some values? I know about the hardware related problems but sometimes it works right. Also even though it is known that precise operations cannot be done, why is such method included in the library? It looks pretty useless due to the fact that it doesn't work always right.
One useful trick in Java is to use the exactness of new BigDecimal(double) and of BigDecimal's toString to show the exact value of a double:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
System.out.println(new BigDecimal(3.14));
System.out.println(new BigDecimal(3.1400000000000001));
System.out.println(new BigDecimal(3.1400000000000006));
}
}
Output:
3.140000000000000124344978758017532527446746826171875
3.140000000000000124344978758017532527446746826171875
3.1400000000000005684341886080801486968994140625
There are a finite number of doubles, so only a specific subset of the real numbers are the exact value of a double. When you create a double literal, the decimal number you type is represented by the nearest of those values. When you output a double, by default, it is shown as the shortest decimal fraction that would round to it on input. You need to do something like the BigDecimal technique I used in the program to see the exact value.
In this case, both 3.14 and 3.1400000000000001 are closer to 3.140000000000000124344978758017532527446746826171875 than to any other double. The next exactly representable number above that is 3.1400000000000005684341886080801486968994140625
Floating point numbers are stored in binary: the decimal representation is just for human consumption.
Using Rick Regan's decimal to floating point converter 3.14 converts to:
11.001000111101011100001010001111010111000010100011111
and 3.1400000000000006 converts to
11.0010001111010111000010100011110101110000101001
which is indeed the next binary number to 53 significant bits.
Like #jgreve mentions this has to do due to the use of float & double primitives types in java, which leads to the so called rounding error. The primitive type int on the other hand is a fixed-point number meaning that it is able to "fit" within 32-bits. Doubles are not fixed-point, meaning that the result of double calculations must often be rounded in order to fit back into its finite representation, which leads sometimes (as presented in your case) to inconsistent values.
See the following two links for more info.
https://stackoverflow.com/a/322875/6012392
https://en.wikipedia.org/wiki/Double-precision_floating-point_format
A work around could be the following two, which gives a "direction" to the first double.
double n = 1.4;
double x = 1.5;
System.out.println(Math.nextAfter(n, x));
or
double n = 1.4;
double next = n + Math.ulp(n);
System.out.println(next);
But to handle floating point values it is recommended to use the BigDecimal class
class Test{
public static void main(String[] args){
float f1=3.2f;
float f2=6.5f;
if(f1==3.2){
System.out.println("same");
}else{
System.out.println("different");
}
if(f2==6.5){
System.out.println("same");
}else{
System.out.println("different");
}
}
}
output:
different
same
Why is the output like that? I expected same as the result in first case.
The difference is that 6.5 can be represented exactly in both float and double, whereas 3.2 can't be represented exactly in either type. and the two closest approximations are different.
An equality comparison between float and double first converts the float to a double and then compares the two. So the data loss.
You shouldn't ever compare floats or doubles for equality; because you can't really guarantee that the number you assign to the float or double is exact.
This rounding error is a characteristic feature of floating-point computation.
Squeezing infinitely many real numbers into a finite number of bits
requires an approximate representation. Although there are infinitely
many integers, in most programs the result of integer computations can
be stored in 32 bits.
In contrast, given any fixed number of bits,
most calculations with real numbers will produce quantities that
cannot be exactly represented using that many bits. Therefore the
result of a floating-point calculation must often be rounded in order
to fit back into its finite representation. This rounding error is the
characteristic feature of floating-point computation.
Check What Every Computer Scientist Should Know About Floating-Point Arithmetic for more!
They're both implementations of different parts of the IEEE floating point standard. A float is 4 bytes wide, whereas a double is 8 bytes wide.
As a rule of thumb, you should probably prefer to use double in most cases, and only use float when you have a good reason to. (An example of a good reason to use float as opposed to a double is "I know I don't need that much precision and I need to store a million of them in memory.") It's also worth mentioning that it's hard to prove you don't need double precision.
Also, when comparing floating point values for equality, you'll typically want to use something like Math.abs(a-b) < EPSILON where a and b are the floating point values being compared and EPSILON is a small floating point value like 1e-5. The reason for this is that floating point values rarely encode the exact value they "should" -- rather, they usually encode a value very close -- so you have to "squint" when you determine if two values are the same.
EDIT: Everyone should read the link #Kugathasan Abimaran posted below: What Every Computer Scientist Should Know About Floating-Point Arithmetic for more!
To see what you're dealing with, you can use Float and Double's toHexString method:
class Test {
public static void main(String[] args) {
System.out.println("3.2F is: "+Float.toHexString(3.2F));
System.out.println("3.2 is: "+Double.toHexString(3.2));
System.out.println("6.5F is: "+Float.toHexString(6.5F));
System.out.println("6.5 is: "+Double.toHexString(6.5));
}
}
$ java Test
3.2F is: 0x1.99999ap1
3.2 is: 0x1.999999999999ap1
6.5F is: 0x1.ap2
6.5 is: 0x1.ap2
Generally, a number has an exact representation if it equals A * 2^B, where A and B are integers whose allowed values are set by the language specification (and double has more allowed values).
In this case,
6.5 = 13/2 = (1+10/16)*4 = (1+a/16)*2^2 == 0x1.ap2, while
3.2 = 16/5 = ( 1 + 9/16 + 9/16^2 + 9/16^3 + . . . ) * 2^1 == 0x1.999. . . p1.
But Java can only hold a finite number of digits, so it cuts the .999. . . off at some point. (You may remember from math that 0.999. . .=1. That's in base 10. In base 16, it would be 0.fff. . .=1.)
class Test {
public static void main(String[] args) {
float f1=3.2f;
float f2=6.5f;
if(f1==3.2f)
System.out.println("same");
else
System.out.println("different");
if(f2==6.5f)
System.out.println("same");
else
System.out.println("different");
}
}
Try like this and it will work. Without 'f' you are comparing a floating with other floating type and different precision which may cause unexpected result as in your case.
It is not possible to compare values of type float and double directly. Before the values can be compared, it is necessary to either convert the double to float, or convert the float to double. If one does the former comparison, the conversion will ask "Does the the float hold the best possible float representation of the double's value?" If one does the latter conversion, the question will be "Does the float hold a perfect representation of the double's value". In many contexts, the former question is the more meaningful one, but Java assumes that all comparisons between float and double are intended to ask the latter question.
I would suggest that regardless of what a language is willing to tolerate, one's coding standards should absolutely positively forbid direct comparisons between operands of type float and double. Given code like:
float f = function1();
double d = function2();
...
if (d==f) ...
it's impossible to tell what behavior is intended in cases where d represents a value which is not precisely representable in float. If the intention is that f be converted to a double, and the result of that conversion compared with d, one should write the comparison as
if (d==(double)f) ...
Although the typecast doesn't change the code's behavior, it makes clear that the code's behavior is intentional. If the intention was that the comparison indicate whether f holds the best float representation of d, it should be:
if ((float)d==f)
Note that the behavior of this is very different from what would happen without the cast. Had your original code cast the double operand of each comparison to float, then both equality tests would have passed.
In general is not a good practice to use the == operator with floating points number, due to approximation issues.
6.5 can be represented exactly in binary, whereas 3.2 can't. That's why the difference in precision doesn't matter for 6.5, so 6.5 == 6.5f.
To quickly refresh how binary numbers work:
100 -> 4
10 -> 2
1 -> 1
0.1 -> 0.5 (or 1/2)
0.01 -> 0.25 (or 1/4)
etc.
6.5 in binary: 110.1 (exact result, the rest of the digits are just zeroes)
3.2 in binary: 11.001100110011001100110011001100110011001100110011001101... (here precision matters!)
A float only has 24 bits precision (the rest is used for sign and exponent), so:
3.2f in binary: 11.0011001100110011001100 (not equal to the double precision approximation)
Basically it's the same as when you're writing 1/5 and 1/7 in decimal numbers:
1/5 = 0,2
1,7 = 0,14285714285714285714285714285714.
Float has less precision than double, bcoz float is using 32bits inwhich 1 is used for Sign, 23 precision and 8 for Exponent . Where as double uses 64 bits in which 52 are used for precision, 11 for exponent and 1for Sign....Precision is important matter.A decimal number represented as float and double can be equal or unequal depends is need of precision( i.e range of numbers after decimal point can vary). Regards S. ZAKIR
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