This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Strange floating-point behaviour in a Java program
I came across this weird phenomenon in Java. Try this statement in a Java program:
System.out.print(4.0-3.1);
The output will be 0.8999999
Why does this happen? And how can it be changed?
I recommend reading What Every Scientist Should Know About Floating-Point Arithmetic. This is standard behavior for floating point math. Most systems (including Java) use IEEE 754 as the standard representation for floating point numbers. Exact, numerical values are not always perfectly represented by this standard, so you often see slight numerical inconsistencies when printing, as you found here.
This is a typical floating point result runded.
You get different results from Float and Double :
System.out.println(4.0f-3.1f);
System.out.println(4.0d-3.1d);
Output:
0.9000001
0.8999999999999999
This is because 0.1 cannot be represented evenly in base 2, and cause a loss of precision. For example :
System.out.println(2.0f-1.9f);
System.out.println(2.0d-1.9d);
Should both return 0.1 but in fact will output :
0.100000024
0.10000000000000009
You will find your answer behind this link.
TL;DR summary: you will have to learn how floating point is represented in computing so you know why these things happen. This is an artifact of floating point representation and you alter it by not using float types if this kind of result is unacceptable to you.
floating point can't represent the value 0.1 or any multiple of 0.1 exactly. It is base 2 where the number system it is displayed in is base 10. There is some data lost when storing base 10 data in base 2 format.
You are having fun with float types. But in binary. In the decimal system there are periodic numbers. Like 1/3 which is 1.33333 and so on. Some numbers in the decimal system are not periodic, but are periodic in the binary system.
Thus calculation is always inaccurate when there is the possibility of periodic numbers.
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I have 2 numbers stored as Double, 1.4300 and 1.4350. When I subtract 1.4350 - 1.4300, it gives me the result: 0.0050000000000001155. Why does it add 1155 to the end and how can I solve this so that it returns 0.005 or 0.0050? I'm not sure rounding will work as I'm working with 2 and 4 decimal numbers.
Oh, I love these... these are caused by inaccuracy in the double representation and floating-point arithmetic is full of these. It is often caused by recurring numbers in binary (i.e. base-2 floating-point representation). For example, in decimal 1/3 = 0.3333' In binary 1/10 is a recurring number, which means it cannot be perfectly represented. Try this: 1 - 0.1 - 0.1 - 0.1 - 0.1. You wont get 0.6 :-)
To solve this, use BigDecimal (preferred) or manipulating the double by first multiplying it something like 10000, then rounding it and then dividing it again (less clean).
Good question... it has caused huge problems in the past. Missiles overshooting targets, satellites crashing after launch, etc. Search the web for some, you'll be amazed!
This is a common pitfall with some computer representations of fractional numbers, see this question or google for floating point precision.
Double is not the right type for very precision floating point calculations, if you want exact results you have to use BigDecimal.
This question already has answers here:
Whats wrong with this simple 'double' calculation? [duplicate]
(5 answers)
Closed 9 years ago.
While I was having fun with codes from Java Puzzlers(I don't have the book) I came across this piece of code
public static void main(String args[]) {
System.out.println(2.00 - 1.10);
}
Output is
0.8999999999999999
When I tried changing the code to
2.00d - 1.10d still I get the same output as 0.8999999999999999
For,2.00d - 1.10f Output is 0.8999999761581421
For,2.00f - 1.10d Output is 0.8999999999999999
For,2.00f - 1.10f Output is 0.9
Why din't I get the output as 0.9 in the first place? I could not make any heads or tails out of this? Can somebody articulate this?
Because in Java double values are IEEE floating point numbers.
The work around could be to use Big Decimal class
Immutable, arbitrary-precision signed decimal numbers. A BigDecimal
consists of an arbitrary precision integer unscaled value and a 32-bit
integer scale. If zero or positive, the scale is the number of digits
to the right of the decimal point. If negative, the unscaled value of
the number is multiplied by ten to the power of the negation of the
scale. The value of the number represented by the BigDecimal is
therefore (unscaledValue × 10^-scale).
On a side note you may also want to check Wikipedia article on IEEE 754 how floating point numbers are stored on most systems.
The more operations you do on a floating point number, the more significant rounding errors can become.
In binary 0.1 is 0.00011001100110011001100110011001.....,
As such it cannot be represented exactly in binary. Depending where you round off (float or double) you get different answers.
So 0.1f =0.000110011001100110011001100
And 0.1d=0.0001100110011001100110011001100110011001100110011001
You note that the number repeats on a 1100 cycle. However the float and double precision split it at a different point in the cycle. As such on one the error rounds up and the other rounds down; leading to the difference.
But most importantly;
Never assume floating point numbers are exact
Other answers are correct, just to point to a valid reference, I quote oracle doc:
double: The double data type is a double-precision 64-bit IEEE 754
floating point. Its range of values is beyond the scope of this
discussion, but is specified in the Floating-Point Types, Formats, and
Values section of the Java Language Specification. For decimal values,
this data type is generally the default choice. As mentioned above,
this data type should never be used for precise values, such as
currency
I want to know how to round a floating-point number to a machine floating number(for example double).
The number "0.01111116" cannot be represented by machine floating point, in some rounding mode, this number should be represented as "0.011111159999999995" with some precision loss.
But I don't know how to finish this in Java?
So I want to know the API to set the rounding mode to get the exact representation of machine floating-point number in Java.
Thanks!
The Java specification does not provide any means to control the floating-point rounding mode. Round-to-nearest is used.
It is not generally possible to arrange for floating-point arithmetic to produce mathematically exact results, so software must be designed to tolerate and adjust for errors or, in very special cases, to get exact results by using extra care.
If you are talking about a literal 0.01111116 in the source code of your program, the Java compiler converts that into the binary floating point representation at compile time.
If you are talking about (say) a String containing the characters "0.01111116", that gets converted to a binary floating point representation if/when you call (for example) Double.parseDouble(...).
Either way, the conversion happens behind the scenes and you don't have any control over the actual rounding. But in a sense it is moot. It is inherent in the nature of the representation that some rounding happens, and the result is generally speaking "the most accurate" you can get from a mathematical perspective ... given the floating point type you have chosen.
If you really wanted the conversion to use different rounding / truncation rules you could either do this after the fact (e.g. round or truncate the converted value), or you could implement your own String to floating-point conversion method.
You won't be able to change the way that the Java compiler converts literals. It is part of the language specification.
So I want to know the API to set the rounding mode to get the exact representation of machine floating-point number in Java.
There is another way of thinking about this.
The exact representation of a machine floating point number is 32 or 64 bits of binary data. You could render the bits of a double as hexadecimal in a couple of ways:
Double::doubleToLongBits or Double::doubleToRawLongBits followed by Long::toHexString gives a precise but unhelpful rendering, or
Double::toHexString gives a hexadecimal floating point representation.
All of these renderings are exact (no rounding errors) representations of the double, but most readers won't understand them. (The "raw" version deals best with edge-cases involving variant NaN values.)
There are equivalent methods for float.
Try commons-math3 Precision http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
double d = 0.1 + 0.2;
System.out.println(d);
d = Precision.round(d, 1); <-- 1 decimal place
System.out.println(d);
output
0.30000000000000004
0.3
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to resolve a Java Rounding Double issue
Please Help,
I programm some calculator in Java. I use double type. Double has 15 digits after the decimal point. I have problem with the following:
1/3 * 3 = 0.9999999999999999
I need 1/3 * 3 = 1
How can I solve this problem?
I keep result in Double. The same problem I have with other mathematical operations, for example
sqrt(6) = 2.449489742783, and next I square the result and I get: 5.999999999999999
You're dealing with inherent limitations of floating-point arithmetic.
Read the paper What Every Computer Scientist Should Know About Floating-Point Arithmetic.
For equality-checking, you should be using something like abs(x-y) < epsilon rather than x == y
For display purposes, you should round to the nearest decimal place that you actually care about.
Certain numbers cannot be represented exactly in binary floating point. 1/3 is one of them. See http://en.wikipedia.org/wiki/Floating_point For that matter, 1/3 cannot be represented exactly in decimal either.
Your calculator should use a java.text.NumberFormat to present the numbers.
The reason why you are seeing this is due to the computers inability to understand infinity.
A computer has limitations, so it does not understand the fact that 1/3 is never-ending. This causes it to round. This can be solved as Jason S posted above. Using these special class, people have started to program ways to computer whether or not something goes to infinity, then attempt to deal with it.
System.out.println((26.55f/3f));
or
System.out.println((float)( (float)26.55 / (float)3.0 ));
etc.
returns the result 8.849999. not 8.85 as it should.
Can anyone explain this or should we all avoid using floats?
What Every Programmer Should Know About Floating-Point Arithmetic:
Q: Why don’t my numbers, like 0.1 + 0.2
add up to a nice round 0.3, and
instead I get a weird result like
0.30000000000000004?
A: Because internally, computers use a
format (binary floating-point) that
cannot accurately represent a number
like 0.1, 0.2 or 0.3 at all.
In-depth explanations at the linked-to site
Take a look at Wikipedia's article on Floating Point, specifically the Accuracy Problems section.
The fact that floating-point numbers
cannot precisely represent all real
numbers, and that floating-point
operations cannot precisely represent
true arithmetic operations, leads to
many surprising situations. This is
related to the finite precision with
which computers generally represent
numbers.
The article features a couple examples that should provide more clarity.
Explaining is easy: floating point is a binary format and so can only represent exactly values that are an integer multiple of 1.0 / (2 to the Nth power) for some natural integer N. 26.55 does not have this property, therefore it cannot be represented exactly.
If you need exact representation (e.g. your code is about accounting and money, where every fraction of a cent matters), then you must indeed avoid floats in favor of other types that do guarantee exact representation of the values you need (depending on your application, for example, just doing all accounting in terms of integer numbers of cents might suffice). Floats (when used appropriately and advisedly!-) are perfectly fine for engineering and scientific computations, where the input values are never "infinitely precise" in any case and therefore the computationally cumbersome burden of exact representation is absolutely not worth carrying.
Well, we should all avoid using floats wherever realistic, but that's a story for another day.
The issue is that floating point numbers cannot exactly represent most numbers we think of as trivial in presentation. 8.850000 probably cannot be represented exactly by a float; and possibly not by a double either. This is because they aren't actually decimal numbers; but a binary representation.