开发者

Rounding in java Float.parseFloat

开发者 https://www.devze.com 2023-01-10 16:00 出处:网络
开发者_开发百科Given the following code, I would expect it to return \"float = 32000.0001\".But instead, it returns \"float = 32000.0\".

开发者_开发百科Given the following code, I would expect it to return "float = 32000.0001". But instead, it returns "float = 32000.0".

System.out.println("float = "+Float.parseFloat("32000.0001"));

Is there something I can do to prevent/control the rounding? I want the full value returned with no rounding.


A float has only 24 bits of precision, which is insufficient to hold the number of digits in your value. The rounding is not due to the parse but to the size of the number. You must use a double if you require floating point, or use BigDecimal if you need arbitrary precision.


You need to be very careful when using floating point while writing software.
Certain decimal numbers do not have exact base 2 representations is one thing to keep in mind. 0.1, 0.01, 0.001 are some examples. So to represent these number in base 2 it needs to round.

Another issue is that you are dealing with a finite set of bits to represent numbers and may experience other rounding errors. Also the further you get away from 0, the more numbers there are that cannot be exactly represented, and therefore rounding takes place.

There are several other issues. Most are mentioned in the paper below. For a formal treatise see this: http://www.scribd.com/doc/5836/What-Every-Computer-Scientist-Should-Know-About-FloatingPoint-Arithmetic

Do not use floats where you need to know an exact number.


If decimal places are of interest to you, I would strongly recommend using BigDecimal instead.

As it is, it's not entirely clear to me (without checking) whether the problem is the parsing from a string or the formatting back to a string.

EDIT: In this case I strongly suspect it's rounding on parsing... given that float has only 7 (guaranteed) significant digits and you're trying to preserve 9.


As others note, float has insufficient precision to hold the full result. The BigDecimal(double) constructor is exact, so it's a handy way to see the representation:

System.out.println(new BigDecimal(32000.0001f)); // as float
System.out.println(new BigDecimal(32000.0001d)); // as double

Which displays this:

32000
32000.00010000000111176632344722747802734375


If you want to avoid rounding, use BigDecimal. The primitive types float and double are faster but they cannot represent many common decimal values.


Floats and Doubles are limited. They are only able to accurately represent fractional portions of numbers as a sum of base two fractions. The fractional portion can be fully represented as the sum of some series like:

1/2 + 0/4 + 1/8 + 1/16 + ...

Unfortunately there are a large number of commonly used numbers which never can be fully represented, like:

1/3, 1/7, 1/9, 5/11 etc.

You must consider whether the number can accurately be represented before you worry about rounding. If this type of accuracy is of extreme importance, then you need to look to a non-Float or non-Double solution.

There are binary decimal libraries which will accurately perform such calculations. They tend to be slower to compute, because there is no specialized hardware to accelerate their calculations. Also, they tend to take up more memory, because you are essentially storing a list of digits.

After you can represent the number you want to the detail you wish, then a rounding solution is simple. Odds are you won't even need a rounding solution; because, the main reason you're trying to round in this case is due to the float not being able to properly represent your value.

0

精彩评论

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

关注公众号