Two equivalent lines of code produce different results

Hey guys, I'm having a slight mindf*ck here.

To simplify my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <cmath>

using namespace std;

double INT_LENGTH(int a){
    for(double i=0; true; i++,a/=10)
        if(!a)                   //returns number of
            return i;            //digits of an int
}

int main()
{
    int m=5553;
    int n=9;

    cout<<"m="<<m+(n%10)*pow(10,INT_LENGTH(m))<<endl;   //<-- why THIS line...
    m+=(n%10)*pow(10,INT_LENGTH(m));                    //
                                                        //
    cout<<"m="<<m;                                      //<-- ...and THIS line
                                                        //    produce different
    return 0;                                           //    results!?
}


The output I get is:
m=95553
m=95552


Why lines 17 and 20 produce different results in the cout?

Why does the value of 'm' get decreased by 1 when I calculate it?

EDIT:
In C++ Shell, the code produces the results as it should (95553 in both lines). But in CodeBlocks, at least mine, it produces the output I specified. Is that a bug or something?
Last edited on
What compiler are you using? Debug MS VS Express 2013 gives be 95553 for both results. I'd suspect it might be a truncation or rounding issue, though, as the result you are sending to cout is a double while assigning to m truncates to int.
I use GNU GCC Compiler.

And your suspicion was right:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    double d=pow(10,4);
    cout<<"d="<<d<<endl;

    int i=pow(10,4);
    cout<<"i="<<i<<endl;

    i=d;
    cout<<"i(from d)="<<i<<endl;

    return 0;
}

This code gives this output:
d=10000
i=9999
i(from d)=10000


So the issue was in returning the value from pow() directly into an int.
I'm still not clear with what causes it, though.
Thanks for help :)
Last edited on
The (GCC) compiler has options for changing how it implements floating point math. Seek "man gcc" with 'math'.

I'd guess that description of option '-mpc80' relates here. The CPU has "extended precision" registers.

The result of pow() is probably converted directly from register into an int.
The other path rounds the content of register into a double. That is where the precision is "lost".

(Just a guess. Floating point math is weird, strange, and bewildering.)
Why is the number of digits a double?

1
2
3
4
5
/*double*/ int INT_LENGTH(int a){
    for( /*double*/ int i=0; true; i++,a/=10)
        if(!a)                   //returns number of
            return i;            //digits of an int
}
Just wondering why you used double in the for loop on line 7? Why not an int because you are counting how times you can divide by 10?

And why this academic question of using int with the pow function? Perhaps it is an arbitrary & obfuscated example to demonstrate the dangers of FP. We may as well have a discussion about why 10 * 0.1 != 1.0

I am sure the pow function uses a series to calc the answer: so assigning to int and expecting a good answer doesn't make sense to me.

What is the result of 9%10? More to the point why?

I hope I haven't come across too rudely :+)

I wrote the INT_LENGTH line before the rest of the code, so I guess I used double because I saw that pow() usually uses doubles as arguments.

9%10 was the part of my full code which I didn't simplify (value of n changed).
I ran into the float issue using pow() with int variables. . .not a good idea!

So when using int values, I just use this:

1
2
3
4
5
int power(int value, int exp)
{
      if (exp == 0) return 1;
      else return value * power(value,exp -1);
}


This does not work for negative exponents, of course. . .but int variables don't have fractions, either.
Last edited on
Topic archived. No new replies allowed.