Comparison of doubles and problems associated with it

Hello ! First of all, my apologies for the horrible formatting, I wasn't able to make it work no matter how hard I tried.
So I've had a problem bugging me for a good bit of time now, an engineer who has been programming for 20 years even tried to help me but kind of failed at it as he did bring me some elements but it has not truly resolved the problem. I have two versions of a program which are, in theory, supposed to give the same answer:

#include <iostream>
#include <math.h>
using namespace std;

int main()
{
int n,p;
cin >> p;
n = 1;
while ( (1/pow(n,2)) > (1/pow(10,p)) )
{
n++;
}
cout << n;
}

and

#include <iostream>
#include <math.h>
using namespace std;

int main()
{
int n,p;
cin >> p;
n = 1;
while ( pow(n,2) < pow(10,p) )
{
n++;
}
cout << n;
}

So, as an example, both these programs will give the same answer if we give it 16.Now if we give them 8, the first one will send back 10001 whereas the second one will send back 10000 (which is the right answer).I know that due to the way doubles are stored, they are not exact values at all. But the problem is that, considering the second program's output,
pow(10000,2) = pow(10,8) (which is true)
But considering the first one's output,
(1/pow(10000,2)) > (1/pow(10,8)) (which is not true)

Therefore, the problem seems to be with the 1/...But even if there was a mistake made in the calculation due to a problematic value (as an exmaple I know that 0.2 cannot be stored, 0.19999999... will always be stored instead), the mistake is supposed to be the same as the exact same calculation is made.

But the program did not find (1/pow(10000,2)) = (1/pow(10,8))
(And it did find (1/pow(100000000,2)) = (1/pow(10,16)) )

There, that's my problem. I hope that someone will be able to help me because it really is bugging me.
Thanks a lot !
Last edited on
I ran both programs and they give the same answers.

C:\Users\Test>test2
2
10
C:\Users\Test>test2
4
100
C:\Users\Test>test2
8
10000
C:\Users\Test>test2
16
100000000
C:\Users\Test>test3
2
10
C:\Users\Test>test3
4
100
C:\Users\Test>test3
8
10000
C:\Users\Test>test3
16
100000000
C:\Users\Test>
The fun thing is that after I read your message, I decided to try to fully build the program and not use a debug version. It worked and gave 10000. But when using the debug version (newly made), it still gave back 10001. I guess the problem is related to the compiler or software... I'm using the GNU GCC Compiler on Code::Blocks, you probably were using something different or a different version.

And I know for sure that the compiler is doing different things for debug and release as when building the release this error occured
c:\mingw\include\math.h: In function 'float hypotf(float, float)':
c:\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope
{ return (float)(_hypot (x, y)); }
(error which I was able to fix)
It would be nice to see the compiler command-line for each version of the build. Some optimizations change the semantics of the generated code (e.g., associativity of floating point operations, or even the lookup tables used) for the sake of speed. See
https://gcc.gnu.org/wiki/FloatingPointMath

Perhaps with that information, along with your platform info and a compiler version, we might be able to pin down where exactly the differences lie.

P.S.: Standard library headers don't end in an ".h". C++ versions of headers borrowed from the C library are prefixed with a leading "c".
#include <math.h> -> #include <cmath>

I'm using Dev-Cpp

If you google POW giving wrong answer, there are several threads.

Some think it's the pow function rounding as it uses a float variable and while I can't confirm that I'd hazard a guess that they may be on the right track.
Comparing doubles is fraught with danger, because of rounding to finite precision. As mbozzi has pointed out, compilers are at liberty to re-order calculations for optimisation etc, and the rounding at intermediate calculations will then change.

I try to avoid testing for equality of two doubles (with ==) as far as possible, and in practice, I usually test for equality of x and y as
if ( abs( x - y ) < TOLERANCE )
with TOLERANCE set to a small number.
Integers shouldn't give the same rounding problems, but their range is more limited. The result of pow() is a float or a double.

If you think this is bad, you should try parallel processing - if you sum over results on all processors you can actually get slightly different results on each run of the same program, due to the intermediate partial sums being rounded in different ways according to the number of processors being used.
Thank you for your answers, I'll keep searching on my side and just mark this as solved, and also thank you mbozzi for reminding me that. I keep going from C to C++ and from C++ to C so sometimes I switch things up a bit, I corrected that.
Topic archived. No new replies allowed.