不能在双打上使用模数?
Posted
技术标签:
【中文标题】不能在双打上使用模数?【英文标题】:Can't use modulus on doubles? 【发布时间】:2012-02-26 16:03:57 【问题描述】:我有一个 C++ 程序(使用 g++ 编译)。我正在尝试将两个双精度数作为操作数应用于模函数,但出现以下错误:
错误:“double”和“double”类型的无效操作数到二进制“operator%”
代码如下:
int main()
double x = 6.3;
double y = 2;
double z = x % y;
【问题讨论】:
如前所述,fmod() 提供了必要的功能。正如尚未注意到的那样,重要的是要意识到fmod
的第二个操作数中的舍入错误可能会导致意外行为。例如,fmod(1, 0.1);
在数学上应该为零,但实际上几乎是 0.1。误差的程度随着商的大小而增加。例如,fmod(9E14, 0.1);
的计算结果约为 0.05,从数学角度来看这是完全错误的。
@supercat 更多细节会很棒。我认为对幕后发生的事情使您所说的话有所了解,但是最好了解您所说的话是真实的原因;看看它在幕后是如何工作的会很有趣(我想我理解但很容易出错)。
浮点值表示精确的整数倍数或 2 的幂的分数。例如,整数文字 0.1 正好是 3602879701896397/36028797018963968(后一个值是 2 的幂)。 fmod(x,0.1)
将 x 除以该精确分数并取余数,而不是除以数值“十分之一”。
可能重复:Why does modulus division (%) only work with integers?
【参考方案1】:
%
运算符用于整数。您正在寻找fmod()
function。
#include <cmath>
int main()
double x = 6.3;
double y = 2.0;
double z = std::fmod(x,y);
【讨论】:
我正在使用 C++ 为 Qt 编程,而 fmod 有一个错误。 fmod(angle, 360) 的结果可以是 360 (WAT?!) @Paul:这可能不是错误。如果angle
是359.9999999
,那么angle
和fmod(angle, 360)
都可能显示为360
。 (根据需要添加更多 9。)尝试以 50 位精度打印值。
@Paul Qt 的 QString::format 将四舍五入。如果这很关键,您将不得不自己四舍五入或检查“360”的输出并将其替换为您自己的值。
@Rohan main(void)
在C++
中是不必要的(它是 C 遗留),您的编辑也没有改进其他任何东西。我把它恢复了。【参考方案2】:
fmod(x, y)
是你使用的函数。
【讨论】:
【参考方案3】:使用<cmath>
中的fmod()
。如果不想包含 C 头文件:
template<typename T, typename U>
constexpr double dmod (T x, U mod)
return !mod ? x : x - mod * static_cast<long long>(x / mod);
//Usage:
double z = dmod<double, unsigned int>(14.3, 4);
double z = dmod<long, float>(14, 4.6);
//This also works:
double z = dmod(14.7, 0.3);
double z = dmod(14.7, 0);
double z = dmod(0, 0.3f);
double z = dmod(myFirstVariable, someOtherVariable);
【讨论】:
为什么不想包含 C 头文件?这就是它的用途。【参考方案4】:你可以实现你自己的模数函数来为你做这件事:
double dmod(double x, double y)
return x - (int)(x/y) * y;
然后您可以简单地使用dmod(6.3, 2)
来获得余数,0.3
。
【讨论】:
仍然不是一个完美的解决方案。 x=10.499999999999998, y=0.69999999999999996 返回 0.69999999999999929 而不是 0.0 @tarpista:这是预期的,带有浮点数。以上是关于不能在双打上使用模数?的主要内容,如果未能解决你的问题,请参考以下文章