This question already has answers here:
Difference between Infinity and NaN (Not a number)
(3 answers)
Closed 5 years ago.
Can anyone explain why the flag value is returning False?
double a = 1.0;
double b = 0.0;
double c = a / b;
boolean flag = Double.isNaN(c);
System.out.println(flag); // False?
System.out.println(c); // Infinity
This is due to the definition of floating-point representation in the IEEE 754 standard. The standard has representations for both "infinity" and "NaN". "Infinity" is for operations that either produce an infinite result (such as 1/0 or tan(pi/2) [*]) or produce a result whose absolute value is larger than the largest possible number the format can represent. More precisely, in math, there really isn't such a thing as an infinite result; rather, it's defined in terms of limits. Thus, 1/0 doesn't exist, but the limit of 1/x as x approaches 0 is infinite.
NaN is returned for "indeterminate forms". In math, these are cases such as 0/0 when the limit can't be determined just by looking at the numerator and denominator. (If you have two functions f(x) and g(x) where the values are both 0 at some point f(a)=g(a)=0, then you can't determine the limit of f(x)/g(x) as x approaches a, without extra work such as L'Hopital's rule.) NaN is also returned for things like taking the square root of a negative number.
In Java, isNan returns true only for actual NaN's, not for infinities. Even though infinity really is "not a number", it doesn't meet the definition of a NaN according to the IEEE standard.
See here for a definition of which operations generate NaN.
[*] Note that "pi" can't be represented exactly in a floating-point number, so this really isn't an operation that could produce an "infinite result" on a computer.
That's what the IEEE-754 standard says. When you divide a non-zero floating point number by zero, it does not return a number, but infinity.
Take a look at this: http://grouper.ieee.org/groups/754/faq.html#exceptions
Related
I understand that the theory of binary numbers, so operation of double numbers is not precise. However, in java, I have no idea why "(double)65 / 100" is 0.65, which is completely correct in decimal number, other than 0.6500000000004.
double a = 5;
double b = 4.35;
int c = 65;
int d = 100;
System.out.println(a - b); // 0.6500000000000004
System.out.println((double) c / d); // 0.65
Java completely messes up has its own way of handling floating-point binary to decimal conversions.
A simple program in C (compiled with gcc) gives the result:
printf("1: %.20f\n", 5.0 - 4.35); // 0.65000000000000035527
printf("2: %.20f\n", 65./100); // 0.65000000000000002220
while Java gives the result (note you only needed 17 digits to see it, but I'm trying to make it more clear):
System.out.printf("%.20f\n", 5.0 - 4.35); // 0.65000000000000040000
System.out.printf("%.20f\n", 65./100); // 0.65000000000000000000
But when using the %a format specifier, both languages printf the underlying hexadecimal (correct) value: 0x1.4ccccccccccd00000000p-1.
So, Java is performing some illegal rounding at some point in the code. The apparent issue here is that Java has a different set of rules to convert binary to decimal, from the Java specification:
The number of digits in the result for the fractional part of m or a is equal to the precision. If the precision is not specified then the default value is 6. If the precision is less than the number of digits which would appear after the decimal point in the string returned by Float.toString(float) or Double.toString(double) respectively, then the value will be rounded using the round half up algorithm. Otherwise, zeros may be appended to reach the precision. For a canonical representation of the value, use Float.toString(float) or Double.toString(double) as appropriate. (emphasis mine)
And in the toString specification:
How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0. (emphasis mine)
So, Java does perform a different binary to decimal conversion from C, but it remains closer to the true binary value than to any other, so the spec guarantees that the binary value can be restored back by a decimal to binary conversion.
Professor William Kahan warned about some Java floating-point issues in this article:
How Java’s Floating-Point Hurts Everyone Everywhere
But this conversion behaviour seems to be IEEE-complaint.
EDIT: I have included information provided by #MarkDickinson in the comments, to report that this Java behaviour, albeit different from C, is documented, and is IEEE-compliant. This has already been explained here, here, and here.
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
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.
This question already has answers here:
Integer division: How do you produce a double?
(11 answers)
Closed 7 years ago.
if I have something like:
long x = 1/2;
shouldn't this be rounded up to 1? When I print it on the screen it say 0.
It's doing integer division, which truncates everything to the right of the decimal point.
Integer division has its roots in number theory. When you do 1/2 you are asking how many times does 2 equal 1? The answer is never, so the equation becomes 0*2 + 1 = 1, where 0 is the quotient (what you get from 1/2) and 1 is the remainder (what you get from 1%2).
It is right to point out that % is not a true modulus in the mathematical sense but always a remainder from division. There is a difference when you are dealing with negative integers.
Hope that helps.
What this expression is doing is it first declares the existence of a long called x, and then assigning it the value of the right hand side expression. The right hand side expression is 1/2, and since 1 and 2 are both integers this is interpreted as integer division. With integer division the result is always an Integer, so something along the lines of 5/3 will return 1, as only one three fits in a five. So with 1/2, how many 2s can fit into 1? 0.
This can in some languages result in some interesting outputs if you write something like
double x = 1/2. You might expect 0.5 in this case, but it will often evaluate the integer value on the right first before assigning and converting the result into a double, giving the value 0.0
It is important to note that when doing this kind of type conversion, it will never round the result. So if you do the opposite:
long x = (long)(1.0/2.0);
then while (1.0/2.0) will evaluate to 0.5, the (long) cast will force this to be truncated to 0. Even if I had long x = (long)(0.9), the result will still be 0. It simply truncates after the decimal point.
It can't round because it's never in a state to be rounded
The expression "1/2" is never 0.5 before assign to long
Now, long x = 1.0/2.0 because the expression on the right before assign is valid for rounding. Unless you get 0.499999999999997...
this question was answered before on this site, you are doing an integer division, if you want to get the 0.5 use:
double x = (double)1/2;
and you will get the value of 0.5 .
There are lots of different rounding conventions, the most common being rounding towards +inf, rounding towards -inf and rounding towards zero. Lots of people assume there's one right way, but they all have different ideas about what that one way should be ;-)
There is no intermediate non-integer result for integer division, but of course the division is done deterministically, and one particular rounding convention will always be followed for a particular platform and compiler.
With Visual C++ I get 5/2 = 2 and -5/2 = -2, rounding towards zero.
The rounding in C, C++ and Java is commonly called "truncation" - meaning drop off the unwanted bits. But this can be misleading. Using 4 bit 2s complement binary, doing what truncation implies gives...
5/2 = 0101/0010 = 0010.1 --> 0010 = 2
-5/2 = 1011/0010 = 1101.1 --> 1101 = -3
Which is rounding towards -infinity, which is what Python does (or at least what it did in Python 2.5).
Truncation would be the right word if we used a sign-magnitude representation, but twos complement has been the de-facto standard for decades.
In C and C++, I expect while it's normally called truncation, in reality this detail is undefined in the standards and left to the implementation - an excuse for allowing the compiler to use the simplest and fastest method for the platform (what the processors division instruction naturally does). It's only an issue if you have negative numbers though - I've yet to see any language or implementation that would give 5/2 = 3.
I don't know what the Java standard says. The Python manual specifies "floor" division, which is a common term for rounding to -infinity.
EDIT
An extra note - by definition, if a/b = c remainder d, then a = (b*c)+d. For this to hold, you have to choose a remainder to suite your rounding convention.
People tend to assume that remainders and modulos are the same, but WRT signed values, they can be different - depending on the rounding rules. Modulo values are by definition never negative, but remainders can be negative.
I suspect the Python round-towards-negative-infinity rule is intended to ensure that the single % operator is valid both as a remainder and as a modulo. In C and C++, what % means (remainder or modulo) is (yes, you guessed it) implementation defined.
Ada actually has two separate operators - mod and rem. With division required to round towards zero, so that mod and rem do give different results.
How can we use them in our codes, and what will cause NaN(not a number)?
Positive infinity means going to infinity in the positive direction -- going into values that are larger and larger in magnitude in the positive direction.
Negative infinity means going to infinity in the negative direction -- going into values that are larger and larger in magnitude in the negative direction.
Not-a-number (NaN) is something that is undefined, such as the result of 0/0.
And the constants from the specification of the Float class:
Float.NEGATIVE_INFINITY
Float.POSITIVE_INFINITY
Float.NaN
More information can be found in the IEEE-754 page in Wikipedia.
Here's a little program to illustrate the three constants:
System.out.println(0f / 0f);
System.out.println(1f / 0f);
System.out.println(-1f / 0f);
Output:
NaN
Infinity
-Infinity
This may be a good reference if you want to learn more about floating point numbers in Java.
Positive Infinity is a positive number so large that it can't be represented normally. Negative Infinity is a negative number so large that it cannot be represented normally. NaN means "Not a Number" and results from a mathematical operation that doesn't yield a number- like dividing 0 by 0.
In Java, the Double and Float classes both have constants to represent all three cases. They are POSITIVE_INFINITY, NEGATIVE_INFINITY, and NaN.
Plus consider this:
double a = Math.pow(10, 600) - Math.pow(10, 600); //==NaN
Mathematically, everybody can see it is 0. But for the machine, it is an "Infinity" - "Infinity" (of same Rank), which is indeed NaN.
1/0 will result in positive infinity.
0/0 will result in Nan. You can use NaN as any other number, eg: NaN+NaN=NaN, NaN+2.0=NaN
-1/0 will result in negative infinity.
Infinity (in java) means that the result of an operation will be such an extremely large positive or negative number that it cannot be represented normally.
The idea is to represent special numbers which can arise naturally from operations on "normal" numbers. You could see infinity (both positive and negative) as "overflow" of the floating point representation, the idea being that in at least some conditions, having such a value returned by a function still gives meaningful result. They still have some ordering properties, for example (so they won't screw sorting operations, for example).
Nan is very particular: if x is Nan, x == x is false (that's actually one way to test for nan, at least in C, again). This can be quite confusing if you are not used to floating point peculiarities. Unless you do scientific computation, I would say that having Nan returned by an operation is a bug, at least in most cases that come to mind. Nan can come for various operations: 0/0, inf - inf, inf/inf, 0 * inf. Nan does not have any ordering property, either.
You can use them as any other number:
e.g:
float min = Float.NEGATIVE_INFINITY;
float max = Float.POSITIVE_INFINITY;
float nan = Float.NaN;
Positive Infinity is a positive number so large that it can't be
represented normally. Negative Infinity is a negative number so large
that it cannot be represented normally. NaN means "Not a Number" and
results from a mathematical operation that doesn't yield a number-
like dividing 0 by 0.
this is not a complete answer(or not clarified enough) - consider this:
double a = Math.pow(10,600) - Math.pow(10,600); //==NaN
mathematically everybody can see it is 0. but for the machine it is an "Infinity" - "Infinity"(of same order) witch is indeed NaN...