-1

Can anyone explain to me why this program:

for(float i = -1; i < 1; i += .1F)
    Console.WriteLine(i);

Outputs this:

-1

-0.9

-0.8

-0.6999999

-0.5999999

-0.4999999

-0.3999999

-0.2999999

-0.1999999

-0.99999993

7.450581E-08

0.1000001

0.2000001

0.3000001

0.4000001

0.5000001

0.6000001

0.7000001

0.8000001

0.9000002

Where is the rounding error coming from??

3

7 Answers 7

3

I'm sure this question must have been asked in some form before but I can't find it anywhere quickly. :)

The answer comes down to the way that floating point numbers are represented. You can go into the technical detail via wikipedia but it is simply put that a decimal number doesn't necessarily have an exact floating point representation...

The way floating point numbers (base 2 floating point anyway like doubles and floats) work [0]is by adding up powers of 1/2 to get to what you want. So 0.5 is just 1/2. 0.75 is 1/2+1/4 and so on.

the problem comes that you can never represent 0.1 in this binary system without an unending stream of increasingly smaller powers of 2 so the best a computer can do is store a number that is very close to but not quite 0.1.

Usually you don't notice these differences but they are there and sometimes you can make them manifest themselves. There are a lot of ways to deal with these issues and which one you use is very much dependant on what you are actually doing with it.

[0] in the slightly handwavey close enough kind of way

3

Floating point numbers are not correct, they are always approximated because they must be rounded!!
They are precise in binary representation.
Every CPU or pc could lead to different results.
Take a look at Wikipedia page

2
  • That's not true. As I've been corrected, FP are precise, but they are precise in binary. It's the conversion to decimal that is approximated, because it must often be rounded. Commented Jul 6, 2012 at 15:18
  • A finite binary fraction can always be represented as a finite decimal number. The reason being that (1/2)^n is never a recurring number therefore a sum of them is not recurring. So you can get a precise decimal representation, it just depends how wide your numbers are. Its only the conversion from decimal to binary that cannot alwasy be done in a precise way (though it is worth noting that not all decimals lose precision in becoming binary floating point numbers).
    – Chris
    Commented Jul 6, 2012 at 15:29
2

The big issue is that 0.1 cannot be represented in binary, just like 1 / 3 or 1 / 7 cannot be represented in decimal. So since the computer has to cut off at some point, it will accumulate a rounding error.

Try doing 0.1 + 0.7 == 0.8 in pretty much any programming language, you'll get false as a result.

In C# to get around this, use the decimal type to get better precision.

2

This will explain everything about floating-point: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

1

The rounding error comes from the fact that Float is not a precise data type (when converted to decimal), it is an approxomation, note in the C# Reference Float is specified as having 7 digits of decimal precision.

3
  • That's not true, and it doesn't answer the question. Commented Jul 6, 2012 at 15:20
  • The question is answered reasonably well - the answer is, the rounding error comes from the lack of decimal precision in the Float. Microsoft C# Reference is very clear that the precision is only 7 digits - the values the OP list are 7 digits long... Commented Jul 6, 2012 at 15:23
  • converting a float to a decimal is not the problem. Its the converting the decimal to float that is the problem. The size (and precision) of a float means that it can always be represented as a decimal accurately.
    – Chris
    Commented Jul 6, 2012 at 15:33
1

It is fundamental to the any floating point variable. The reasons are complex but there is plenty of information if you google it.

Try using Decimal instead.

1

As other posters have intimated, the problem stems from the assumption that floating point numbers are a precise decimal representation. They are not- they are a precise binary (base-2) representation of a number. The problem you are experiencing is that you cannot always express a precise binary number in decimal format- just like you cannot express 1/3 in decimal format (.33333333...). At some point, rounding must occur.

In your example, rounding is occurring when you express .1F (because that is not a value that can be expressed precisely in base-2).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.