为啥我的 std::pow 和 std::fmod 结果错误? [复制]
Posted
技术标签:
【中文标题】为啥我的 std::pow 和 std::fmod 结果错误? [复制]【英文标题】:Why I get wrong result with std::pow and std::fmod? [duplicate]为什么我的 std::pow 和 std::fmod 结果错误? [复制] 【发布时间】:2018-01-31 20:19:48 【问题描述】:下面这几行代码在计算后返回错误的结果,会不会是“double”类型的逼近造成的?
int base = 20, exp = 27, mod = 123;
std::fmod(std::pow(base, exp), mod)
有没有办法得到正确的计算? (也有 base = 128,Exp >= 50 mod >= 200?) 对不起我的英语不好
【问题讨论】:
正确的计算方法是什么?你得到了什么? 有一个可以应用的数学定律,即result = result*base % mod
循环exp
次将给出与base<sup>exp</sup> % mod
相同的结果。不过不记得叫什么了。无论如何,它可以让你计算巨大的数字并且永远不会留下整数空间。
当调用std::fmod
时,您的变量将提升为double
,并且该类型对于您的测试用例没有足够的精度:ideone.com/hBbKyV。如果你需要计算更大的值,你应该利用模运算。
【参考方案1】:
您的问题是浮点错误。传入pow()
时,数字转换为双精度数,双精度数可以存储54位有效二进制数字,不足以准确存储20^27。最好通过像这样重复 result = result * base % mod
exp 次来利用模运算:
int result = 1;
for(int i = 0; i < exp; i++)
result = result * base % mod;
只要输入不是太大,这应该将值保持在 int 限制之下并在几秒钟内运行。如需更快的算法,请使用binary exponentiation。
【讨论】:
以上是关于为啥我的 std::pow 和 std::fmod 结果错误? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
c++11 下 fmod(和其他)的不同行为,至少在 Visual Studio 中
标准对 std::pow、std::log 等 cmath 函数有啥看法?