使用fmod函数时,我得到了一些非常令人困惑的结果。
以下代码:
double x = pow(142, 35);
double y = fmod(x, 221);
std::cout << x << std::endl << y;
输出:
2.13842e+75
206
但是当硬编码x值时:
double x = pow(142, 35);
double y = fmod(2.13842e+75, 221);
std::cout << x << std::endl << y;
输出更改为:
2.13842e+75
14
我不知道这是什么原因,它在我的程序中创造了一些丑陋的错误。任何见解将不胜感激。提前谢谢。
答案 0 :(得分:3)
所以当我输出第一个结果时这样:
std::cout << std::fixed << x << std::endl << y << std::endl;
我明白这一点:
2138415301692701661114266637060519453227273059369895888628790658837784821760.000000
206.000000
当我使用上面这个数字表示x
的值时,如下所示:
double y = fmod(2138415301692701661114266637060519453227273059369895888628790658837784821760.000000, 221);
然后我从第一个示例中获得206
y
的结果,主要问题是您使用IEEE double达到了限制。
更新
modular power的算法:
template <typename T>
T modpow(T base, T exp, T modulus) {
base %= modulus;
T result = 1;
while (exp > 0) {
if (exp & 1) result = (result * base) % modulus;
base = (base * base) % modulus;
exp >>= 1;
}
return result;
}
我从here找到的会给你正确的结果。
答案 1 :(得分:0)
这里有几个问题。
首先,print语句会截断实际值。 C ++的默认值 cout的精度为6.它只打印6位小数。就这样 以下两个打印产生不同的结果,即使它们打印相同 变量:
double x = pow(142, 35);
std::cout << x << std::endl << y;
// prints 2.13842e+75
std::cout << std::fixed << x << std::endl << y << std::endl;
// prints 2138415301692701661114266637060519453227273059369895888628790658837784821760.0000000
请注意,std :: fixed操纵器用于更改输出。谢谢 @Shafik Yaghmour提供操纵者。
其次,由于缺乏精确度,即使上面打印的值也不正确
一双。 IEEE double使用52位来存储尾数。这是
足以达到15至17位精度。你需要使用一个arbituary
精确计算器来确定实际结果(例如bc
命令行实用程序)。
% bc
142^35
2138415301692701650291828893190357329823022421032574372998179511073104723968
(142^35)%221
12
查看这两个值,前17个数字按预期匹配。
请参阅http://en.wikipedia.org/wiki/Double-precision_floating-point_format 关于IEEE双重限制的其他细节。