使用cmath的fmod(C ++)时出现不一致

时间:2014-03-28 03:03:25

标签: c++ cmath

使用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

我不知道这是什么原因,它在我的程序中创造了一些丑陋的错误。任何见解将不胜感激。提前谢谢。

2 个答案:

答案 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双重限制的其他细节。