我有一个处理任意大网格的函数。由于使用std::pow
,我需要计算另一个数字的幂的网格是否适合双精度。如果不能,我想采用不同的分支并使用gnu multiprecision库而不是普通的。
有没有快速查看是否:
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
}
我对checkPowFitsDouble感到非常难过;也许有一些我不知道的数学技巧。
答案 0 :(得分:4)
除非它对性能至关重要,否则建议尝试并查看。如果它溢出双倍,std::pow
将返回HUGE_VAL
。因此类似于:
double val = std::pow(a, b);
if(val != HUGE_VAL) {
...
} else {
mpz_t c;
//...
}
答案 1 :(得分:3)
您可以在测试中轻松使用反向功能:
if ( std::log( DBL_MAX ) / std::log( a ) < b ) {
// std::pow( a, b ) will not overflow...
} else {
}
做战俘可能同样好,看看是否合适 成功:
errno = 0;
double powab = std::pow( a, b );
if ( errno == 0 ) {
// std::pow succeeded (without overflow)
} else {
// some error (probably overflow) with std::pow.
}
只需计算std::log( a )
,您就不会有太多时间。
(std::log( DBL_MAX )
当然是一个常数,所以只需要
计算一次。)
答案 2 :(得分:2)
使用对数基数10,您可以推断出std:pow(a, b)
有log(a^b) = b log a
个数字。然后,您可以轻松地查看它是否适合双精度值,这可以使值达到DBL_MAX。
但是,此方法执行额外的计算而不仅仅计算a^b
一次。首先使用GMP测量版本,然后查看检查溢出是否实际上提供了任何可衡量和可重现的好处。
编辑:忽略这一点,std::pow
已经返回一个适当的值,以防发生溢出,所以使用它。
答案 3 :(得分:2)
检查指数是否会溢出的常用技巧是使用对数。这个想法基于这些关系:
a^b <= m <=> log(a^b) <= log(m) <=> b * log(a) <= log(m) <=> b <= log(m) / log(a)
例如,
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";
}
这给出了这个想法。我希望这会有所帮助。