0

Possible Duplicate:
Floating point inaccuracy examples

I have the following line inside a WHILE loop, in C/C++:

while(...)
{
    x = x + float(0.1); // x is a float type. Is the cast necessary?
}

x starts as 0. The thing is, after my first loop, x = 0.1. That's cool. After my second loop, x = 0.2. That's sweet. But, after my third loop, x = 0.3000001. That's not OK. I want it to have 0.3 as value, not 0.3000001. Can it be done? Am I looping wrongly?

Community
  • 1
  • 1
iL_Marto
  • 3
  • 1
  • 6

5 Answers5

3

Floating point does not work that way there are infinitely many real numbers between any two real numbers and only a finite amount of bits this means that in almost all cases the floating point representation is approximate. Read this link for more info.

rerun
  • 25,014
  • 6
  • 48
  • 78
  • This statement does not explain why floating point arithmetic is approximate. This can be seen because the same statement is true of integers (there are infinitely many integers but only a finite amount of bits), yet addition, subtraction, and multiplication on integers is exact (up to overflow). – Eric Postpischil Jan 16 '13 at 15:08
  • Perhaps better stated as: Pick any two integers and there will be a finite number of integers between them. Pick any two real numbers (floating point) and there will be an infinite number of real numbers between them. – user7116 Jan 16 '13 at 15:31
1

It's not the loop, it's just how floats are represented in memory. You don't expect all real numbers to be directly representible in a limited number of bytes, right?

A 0.3 can't be exactly represented by a float. Try a double (not saying it will work, it probably won't, but the offset will be lower).

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
1

This is a common misconception with floating point numbers. 0.3 may not be exactly representable with 32bit or 64bit binary floating point. Lots of numbers are not exactly representable. Your loop is working fine ignoring the unnecessary syntax.

while (...)
{
    x += 0.1f; /* this will do just fine in C++ and C */
}

If this doesn't make sense consider the fact that there are an infinite number of floating point numbers...with only a finite number of bits to describe them.

Either way, if you need exact results you need to use a decimal type of the proper precision. Good news though, unless you're doing calculations on money you likely do not need exact results (even if you think you do).

Community
  • 1
  • 1
user7116
  • 63,008
  • 17
  • 141
  • 172
  • The loop is not working fine, for two reasons. One, it adds a value containing an error (`.1` in the source code is not exactly .1) and accumulates that error from iteration to iteration. Two, the addition adds more errors, as its result is rounded in each iteration. Both of these are avoidable to the extent that the floating point value that is nearest the exact mathematical value can be computed, producing a better result than simply adding `.1f` in each iteration. – Eric Postpischil Jan 16 '13 at 15:10
  • I had missed the bit about his request actually being `i/10.`, which certainly simplifies matters. That being said, if he'd like to add a constant value which is not representable iteratively, he'll have to live with some error. – user7116 Jan 16 '13 at 15:29
1

Code such as this:

for (int i = 0;… ; ++i)
{
    float x = i / 10.f;
    …
}

will result in the value of x in each iteration being the float value that is closest to i/10. It will usually not be exact, since the exact value of i/10 is usually not representable in float.

For double, change the definition to:

    double x = i / 10.;

This will result in a finer x, so it will usually be even closer to i/10. However, it will still usually not be exactly i/10.

If you need exactly i/10, you should explain your requirements further.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thanks for the answer, Eric. Indeed, I need exactly i/10. I'm detecting collisions. So, when I ask, for instance if a figure has reached X>=10, but it occurs that X is 9.9999998, I have kind of a problem. I would really need to loop 0.1, 0.2, 0.3, 0.4... Can it be done? – iL_Marto Jan 16 '13 at 15:20
  • @iL_Marto: then you need a base-10 number system and `float`/`double` will not work for you. – user7116 Jan 16 '13 at 15:27
  • @sixlettervariables: That is not an accurate statement. A decimal floating point system is one solution for calculating i/10 exactly, but it has high computational cost (is slow) on common platforms. Another method, with IEEE 754 binary, is to set the rounding direction to upward, evaluate `x = i/10.f`, and then use the test `t >= x`. For a float `t`, this will return true off `t` is greater than exactly i/10. This is because `t`, being a `float`, cannot have any value that is greater than i/10 but less than `i/10.f`. However, there is a cost on some platforms for changing the rounding mode. – Eric Postpischil Jan 16 '13 at 15:33
  • @EricPostpischil: My statement was regarding exact decimal representation in all cases, not just `i/10.f`. If the OP has a requirement for this, such as in calculations of monies, they must use a decimal type. Computational costs are typically related to the precision required for the problem at hand. If exact increments of `0.1` are required, then the computational cost is acceptable. – user7116 Jan 16 '13 at 15:41
0

NO the cast is not necessary in this case

float x;
x = x + float(0.1);

You can simply write

x+= 0.1
MOHAMED
  • 41,599
  • 58
  • 163
  • 268