4

According to http://en.cppreference.com/w/cpp/numeric/math/pow , when std::pow is used with integer parameters, the result is promoted to a double.

My question is then the following:

How safe is to compare an integer type with the result of a std::pow(int1, int2)? For example, can the if below evaluate to true?

std::size_t n = 1024;
if(n != std::pow(2, 10))
    cout << "Roundoff issues..." << endl;

That is, is it possible that the result on the rhs can be something like 1023.99...9 so when converted to size_t becomes 1023?

My guess is that the response in a big NO, but would like to know for sure. I am using these kind of comparisons when checking for dimensions of matrices etc, and I wouldn't like to use a std::round everywhere.

4
  • 2, 10 and 1024 can all be perfectly represented by a double. You should be fine as long as the inputs and output will fit into 53 bits (assuming IEEE-754 double) Commented Nov 15, 2014 at 1:43
  • 1
    @Praetorian You should tell that to user1257. stackoverflow.com/questions/15851636/is-this-a-g-bug Commented Nov 15, 2014 at 2:07
  • @PascalCuoq That's interesting, and horrible. I'm not able to reproduce that on gcc4.4.7, 4.8, 4.9 or MinGW gcc4.9; but it's good to be aware of that problem. Thank you. Commented Nov 15, 2014 at 2:14
  • So I guess the safest bet is to use std::lround before assigning to an integral type. Thanks all for the answers! Commented Nov 15, 2014 at 3:01

4 Answers 4

5

It is funny you should ask, because someone else on StackOverflow had a question that was caused by the very fact that pow applied to small integers did not compute the obvious result on their platform (see also my writeup).

So yes, when applying pow to small integers, both arguments and ideal mathematical result are exactly representable. This does not force the implementation of exp to return the mathematical result, because no standard specifies that pow cannot be inaccurate by more than one ULP. And at least one very popular platform provides by default a pow function that does not compute pow(10, 2) as 100, but you are free to take you chances with pow(2, N) and perhaps it will happen to always return the integer you are entitled to expect.

Sign up to request clarification or add additional context in comments.

2 Comments

Except you should never use pow(2, N), because ldexp(1, N) is better (faster and guaranteed exact result)
@BenVoigt nice to know, thanks, although I gave 2^N as an example. In reality I'm using D^N, where D can be any integer, not just 2.
3

pow on integer arguments when the result is exactly-representable should give you the right answer all the time. Problem is, it doesn't. There are modern platforms (lots of Linux distributions, for instance, both old and recent), where it doesn't. It's not too hard to find a bunch of SO questions where people give pow really nice inputs and it returns a horribly wrong answer.

Comments

0

For that specific example, it should always return false, especially since you are using type int, so that wouldn't have rounding errors.

The places where you would want to be cautious about rounding errors is when you're comparing two different arithmetic functions that return floats or doubles with long decimals. Many times they would return as unequal due to different rounding and different operations occurring.

Comments

0

As several answers have pointed out even though for small numbers the result should be exactly representable there are some low quality implementations.

For the case where you are using const expressions such as:

std::pow(2, 10)

many compilers will use builtin functions for example both gcc and clang will use builtin functions which will probably use something like a lookup table or a simpler formula for these trivial cases. We can see for the above case using godbolt that gcc computes the value at compile time:

movl    $1024, %esi     

These results are more likely to be correct as the question C: i got different results with pow(10,2) and pow(10,j), j=2; demonstrates.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.