开发者

Why do floats seem to add incorrectly in Java? [duplicate]

This question already has answers here: 开发者_如何学C Closed 11 years ago.

Possible Duplicates:

Is JavaScript's Math broken?

Java floating point arithmetic

I have the current code

for(double j = .01; j <= .17; j+=.01){
            System.out.println(j);
        }

the output is:

0.01
0.02
0.03
0.04
0.05
0.060000000000000005
0.07
0.08
0.09
0.09999999999999999
0.10999999999999999
0.11999999999999998
0.12999999999999998
0.13999999999999999
0.15
0.16
0.17

Can someone explain why this is happening? How do you fix this? Besides writing a rounding function?


Floats are an approximation of the actual number in Java, due to the way they're stored. If you need exact values, use a BigDecimal instead.


They are working correctly. Some decimal values are not representable exactly in binary floating point and get rounded to the closest value. See my answer to this question for more detail. The question was asked about Perl, but the answer applies equally to Java since it's a limitation of ALL floating point representations that do not have infinite precision (i.e. all of them).


As suggested by @Kaleb Brasee go and use BigDecimal's when accuracy is a must. Here is a link to a nice explanation of tiny details related to using floating point operations in Java http://firstclassthoughts.co.uk/java/traps/java_double_traps.html

There is also a link to issues involved with using BigDecimal's. Highly recommended to read them both. It really helped me. Enjoy, Boro.


We humans are used to think in 'base 10' when we deal with floating point numbers 'by hand' (that is, literally when writing them on paper or when entering them into a computer). Because of this, it is possible for us to write down an exact representation of, say, 17%. We just write 0.17 (or 1.7E-1 etc). Trying to represent such a trivial thing as a third can not be done exactly with that system, because we have to write 0.3333333... with an infinite number of 3s, which is impossible.

Computers dealing with floating point not only have a limited number of bits to represent the mantissa (or significand) of the number, they are also restricted to express the mantissa in the base of two. That means that most percentages (which we humans with our base 10 floating point convention always can write exactly, like for example '0.17') are impossible for the computer to store exactly. Fractions like 0%, 25%, 50%, 75% and 100% can be expressed exactly as a floating point number in a computer, because it consists of either halves (2E-1) or quarters (2E-4) which fits nicely with a digital representation of a number. Percentage values like 17% or even trivial ones (for us humans!!) like 10% or 1% are as impossible for computers to store exactly simply because those numbers are, for the binary floating point system what the 'one third' is for the human (base 10) floating point system.

But if you carefully pick your floating point values, so they always are made of a whole number of 1/2^n where n might be 10 (meaning an integer number of 1/1024), then they can always be stored exactly without errors as a floating point number. So if you try to store 17/1024 in a computer, it will go smoothly. You can actually store it without error even using the 'human base 10' decimal system (but you would go nuts by the number of actual digits you have to deal with).

This is some reason I believe why some games express angles in a unit where a whole 360 degree turn is 256 angle units. Can be expressed without loss as a floating point number between 0 and 1 (where 1 means you go a full revolution).


It's normal in double representation on the computer. You lose some bits then you will have such results. Better solution is to do this:

for(int j = 1; j <= 17; j++){
    System.out.println(j/100.0);
}


This is because floating point values are inherently not the same as reals in the mathematical sense.

In a computer, there is only a fixed number of bits that can be used to represent value. This means there are a finite number of values that it can hold. But there are an infinite amount of real numbers, thus not all of them can be represented exactly. But usually the value is something close. You can find a more detailed explanation here.


That is because of the limitations of IEEE754 the binary format to get the most out of 32 bit.


As others have pointed out, only numbers that are combinations of powers of two are exactly representable in (bianary) floating point format

If you need to store arbitrary numbers with arbitrary precision, then use BigDecimal.

If the problem is just a display issue, then you can get round this in how you display the number. For example:

String.format("%.2f", n)

will format the number to 2 decimal places.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜