Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange floating-point behaviour in a Java program [duplicate]

Tags:

java

math

In my program I have one array with 25 double values 0.04 When I try to sum these values in a loop I get following results:

0.0 + 0.04 = 0.04
0.04 + 0.04 = 0.08
0.08 + 0.04 = 0.12
0.12 + 0.04 = 0.16
0.16 + 0.04 = 0.2
0.2 + 0.04 = 0.24000000000000002
0.24000000000000002 + 0.04 = 0.28
0.28 + 0.04 = 0.32
0.32 + 0.04 = 0.36
0.36 + 0.04 = 0.39999999999999997
0.39999999999999997 + 0.04 = 0.43999999999999995
0.43999999999999995 + 0.04 = 0.4799999999999999
0.4799999999999999 + 0.04 = 0.5199999999999999
0.5199999999999999 + 0.04 = 0.5599999999999999
0.5599999999999999 + 0.04 = 0.6
0.6 + 0.04 = 0.64
0.64 + 0.04 = 0.68
0.68 + 0.04 = 0.7200000000000001
0.7200000000000001 + 0.04 = 0.7600000000000001
0.7600000000000001 + 0.04 = 0.8000000000000002
0.8000000000000002 + 0.04 = 0.8400000000000002
0.8400000000000002 + 0.04 = 0.8800000000000002
0.8800000000000002 + 0.04 = 0.9200000000000003
0.9200000000000003 + 0.04 = 0.9600000000000003

Why on earth could that happen?!

like image 313
Stella Avatar asked Nov 29 '08 13:11

Stella


People also ask

What are the 2 types of floating point variables in Java?

In Java, floating-point numbers are represented by the types float and double.

What is the main problem with floating point representation?

Accuracy in floating point representation is governed by number of significant bits, whereas range is limited by exponent. Not all real numbers can exactly be represented in floating point format.

Can you multiply floats in Java?

Example: Multiply Two Floating-Point Numbersfirst and second are then multiplied using the * operator and the result is stored in a new float variable product . Finally, the result product is printed on the screen using println() function.

What is double precision floating point in Java?

Double-precision floating-point format (sometimes called FP64 or float64) is a floating-point number format, usually occupying 64 bits in computer memory; it represents a wide dynamic range of numeric values by using a floating radix point.


3 Answers

Other answers mentioned why, but not how to avoid it.

There are several solutions:

  • Scaling: if all your numbers are multiples of 0.01 (for instance), multiply everything by 100 and use integer arithmetic (which is exact).
  • Numeric type: if your language has a numeric type (like a numeric type in SQL), you can use it.
  • Arbitrary precision rationals: use a bignum library like GMP, which allows you to represent these numbers as the ratio of two integers.
  • Decimal floating point: if you have a decimal floating point like the one in IEEE-754r, you can use it.
like image 136
CesarB Avatar answered Oct 26 '22 17:10

CesarB


The most common storage for floating-point values in programming languages - IEEE singles and doubles - does not have exact representations for most decimal fractions.

The reason is that they store values in binary floating-point format, rather than decimal floating-point format. The only fractional values which can be represented exactly are those which are sums of negative powers of two. Numbers like:

  • 0.5 (2^-1)
  • 0.125 (2^-3)
  • 0.625 (2^-1 + 2^-3)

Etc.

What you are seeing is the fact that representations of numbers like 0.96 are not exactly representable, because they are not expressible as a sum of negative powers of two. Thus, when printed out with full precision as a decimal fraction, they won't match the original value.

like image 20
Barry Kelly Avatar answered Oct 26 '22 19:10

Barry Kelly


See also "What Every Computer Scientist Should Know About Floating Point"

like image 38
John with waffle Avatar answered Oct 26 '22 17:10

John with waffle