I have this strange precission problem. When using unsigned long for integers with many digits, I have a strange problem with pow(). I use a cast of unsigned long, but it does not perform well. When using double, it gets perfect. That wouldn't be strange if I were crossing the limits of definition of unsigned long, but the example shows that this is not the case. I would expect the precission problem to be evident in floating point precission (decimals), not in the integers of a simple summatory. I include the results, because different compilers I guess will get different results, I use CodeBlocks in a Windows OS.
#include <iostream>
#include <math.h>
usingnamespace std;
int main()
{
double sum = 0;
unsignedlong upper_limit;
for(int i=0;i<9;i++){
sum += 1*(unsignedlong)pow(10, i);
} // for
cout << sum << endl;
cout << "Sum minus 111111111:" << endl << (sum - 111111111) << endl;
// returns -4 instead of 0. When changed unsigned long in the cast by double, it works!!
upper_limit = 211111111;
cout << (upper_limit - 3);
// evidence that the limits are not crossed
return 0;
}
pow returns floating point values with some degree of precision. It does not return exact number, but the difference is usually not sees as not many people neew dwole precision and output is generally rounded so it is not apparent.
For example pow(10, 2) can return 99.99999999999999 It would be rounded to 100 in output and generally precision loss when summing will not accumulate enough to change visible results (you can see it by manually increasing output precision).
Casting value to integral type truncates it: 99.99 becomes 99 and slight deviations from actual value not worth mention becomes a huge problem. Use proper rounding before casting. Or just eschew casts altogether and simply sum doubles. Or drop your double datatype and use only integral types, replacing std::pow() with integer version.