pow() returning wrong result under specific condit

2019-06-26 13:19发布

问题:

I have been creating a short program for implementing Sieve of Eratosthenes. In he program, I have used int startingPoint which held the value of the current prime number, which had it's multiplications being marked non-prime, starting from its square. I used the pow() function to calculate the square of the starting point in the current loop. While doing so, I came across a weird phenomenon. When startingPoint was equal to 5, then after int i = pow(startingPoint,2) the value of i was 24, instead of 25. This phenomenon occurred only when startingPoint was equal to 5. Afterwards, I ran a few tests, that leaded to the following code snippet:

#include <iostream>
#include <math.h>

int main()
{
    int p=5;

    int num1 = pow(5,2);
    int num2 = pow(p,2);
    float num3 = pow(p,2);
    int num4 = floor(pow(p,2));

    std::cout.precision(10);

    std::cout<<num1<<std::endl; //25
    std::cout<<num2<<std::endl; //24
    std::cout<<std::fixed<<num3<<std::endl; //25.0000000000
    std::cout<<num4<<std::endl; //25            
}

As it can be seen, if I call pow with int literals, the result will be the actual square of the number. However, if I call it using int p=5, then what pow returns is actually one lower than the expected result. If I pass the result into a float variable, it also recieves the correct result.

Now, I know the way pow calculates powers is via approximation, and thus, errors such as this when converting to integer may occur. I might just let it be like that. But what REALLY made me stop and think is what happens with num4. pow(p,2) casted to int returns 24. But floor(pow(p,2)) casted to int returns 25. So the floor function, which, by standard rounds a number down, somehow makes the returned value cast into a higher integer value.

My question in short: Just how does that happen? (I was using gcc 5.3.0 through MinGW)

Edit: As I already stated in the question, I can accept the reason behind pow return value being casted into a lower integer value, but what I really can't comprehend (and I haven't seen this being brought up anywhere else either) is how floor fixes that. How can floor make the return value of pow actually cast into a higher integer value? Now THAT is the real question.

标签: c++ gcc pow