Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my integer math with std::pow giving the wrong answer?

Consider the following piece of code:

#include <iostream> #include <cmath>  int main() {     int i = 23;     int j = 1;     int base = 10;     int k = 2;     i += j * pow(base, k);     std::cout << i << std::endl; } 

It outputs "122" instead of "123". Is it a bug in g++ 4.7.2 (MinGW, Windows XP)?

like image 335
user1257 Avatar asked Apr 06 '13 13:04

user1257


People also ask

Does POW work with integers?

The pow() function takes 'double' as the arguments and returns a 'double' value. This function does not always work for integers.

What is the result of math POW 0 1?

pow treats 0**0 as 1 . This is the oldest defined version. If the power is an exact integer the result is the same as for pown , otherwise the result is as for powr (except for some exceptional cases).

Is std :: pow slow?

If you are using double precision ( double ), std::pow(x, n) will be slower than the handcrafted equivalent unless you use -ffast-math, in which case, there is absolutely no overhead. The overhead without using the compiler option is quite large, around 2 orders of magnitude, starting from the third power.


1 Answers

std::pow() works with floating point numbers, which do not have infinite precision, and probably the implementation of the Standard Library you are using implements pow() in a (poor) way that makes this lack of infinite precision become relevant.

However, you could easily define your own version that works with integers. In C++11, you can even make it constexpr (so that the result could be computed at compile-time when possible):

constexpr int int_pow(int b, int e) {     return (e == 0) ? 1 : b * int_pow(b, e - 1); } 

Here is a live example.


Tail-recursive form (credits to Dan Nissenbaum):

constexpr int int_pow(int b, int e, int res = 1) {     return (e == 0) ? res : int_pow(b, e - 1, b * res); } 
like image 193
Andy Prowl Avatar answered Sep 30 '22 20:09

Andy Prowl