How can I check if std::pow will overflow double

▼魔方 西西 提交于 2021-01-28 03:22:15

问题


I have a function that deals with arbitrarily large grids. I need to compute if a grid to the power of another number will fit into a double due to using std::pow. If it cannot, I want to take a different branch and use gnu multiprecision library instead of normal.

Is there a quick way to see if:

int a = 1024;
int b = 0-10;

if(checkPowFitsDouble(a, b)) {
    long c = static_cast<long>(std::pow(a, b)); //this will only work if b < 6
} else {
    mpz_t c; //yada yada gmp
}

I am completely stumped on checkPowFitsDouble; perhaps there is some math trick I don't know of.


回答1:


A common trick to check whether exponentiations will overflow uses logarithms. The idea is based on these relationships:

a^b <= m <=> log(a^b) <= log(m) <=> b * log(a) <= log(m) <=> b <= log(m) / log(a)

For instance,

int a = 1024;

for (int b = 0; b < 10; ++b) {
    if (b * std::log(a) < std::log(std::numeric_limits<long>::max())) {
        long c = std::pow(a, b);
        std::cout << c << '\n';
    }
    else
        std::cout << "overflow\n";
}

This gives the idea. I hope this helps.




回答2:


Unless it's particularly performance-critical, the suggestion would be to try it and see. If it overflows a double, std::pow will return HUGE_VAL. Hence something like:

double val = std::pow(a, b);
if(val != HUGE_VAL) {
    ...
} else {
    mpz_t c; 
    //...
}



回答3:


You can easily use the reverse functions in the test:

if ( std::log( DBL_MAX ) / std::log( a ) < b ) {
    //  std::pow( a, b ) will not overflow...
} else {
}

It might be just as good to just do the pow, and see if it succeeds:

errno = 0;
double powab = std::pow( a, b );
if ( errno == 0 ) {
    //  std::pow succeeded (without overflow)
} else {
    //  some error (probably overflow) with std::pow.
}

You won't gain much time by just calculating std::log( a ). (std::log( DBL_MAX ) is, of course, a constant, so only needs to be calculated once.)




回答4:


With a logarithm base 10, you can deduce that std:pow(a, b) has log(a^b) = b log a digits. You can then trivially see if it fits a double, which can fit values up to DBL_MAX.

However, this method performs additional computation than just computing a^b once. Measure a version with GMP first and see if checking for overflow actually provides any measurable and reproducible benefits.

EDIT: Ignore this, std::pow already returns an appropriate value in case an overflow occurs, so use that.



来源:https://stackoverflow.com/questions/18609085/how-can-i-check-if-stdpow-will-overflow-double

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!