不能在双打上使用模数吗?


185

我有一个C ++程序(使用g ++编译)。我试图将两个双精度数作为操作数应用于模数函数,但出现以下错误:

错误:类型为“ double”和“ double”的无效操作数为二进制“ operator%”

这是代码:

int main() {
    double x = 6.3;
    double y = 2;
    double z = x % y;
}

12
如前所述,fmod()提供了必要的功能。尚未注意到,重要的是要认识到,第二个操作数的舍入错误fmod可能会导致意外行为。例如,在fmod(1, 0.1);数学上应为零,但实际上几乎为0.1。误差的程度随商的大小而增加。例如,fmod(9E14, 0.1);计算得出的值约为0.05,这从数学的角度来看完全是错误的。
2013年

1
@supercat更多细节会很棒。我认为应该对幕后发生的事情有一个了解,以使您说出的事实是正确的,但最好能弄清为什么您说的是事实。看看它在幕后的工作方式会很有趣(我想我理解,但很容易出错)。
RastaJedi '16

3
浮点值表示精确的整数倍或2的幂的分数。例如,整数文字0.1恰好是3602879701896397/36028797018963968(后一个值是2的幂)。 fmod(x,0.1)将x除以该精确分数并取余数,而不是除以数值“十分之一”。
超级猫

Answers:


272

%运营商是整数。您正在寻找fmod()功能

#include <cmath>

int main()
{
    double x = 6.3;
    double y = 2.0;
    double z = std::fmod(x,y);

}

我正在用C ++为Qt编程,而fmod那里有一个bug。fmod(angle,360)的结果可以是360(WAT ?!)
保罗

7
@Paul:那可能不是错误。如果angle为,359.9999999则两个anglefmod(angle, 360)都可能显示为360。(根据需要添加更多9s。)尝试以50位数的精度打印值。
基思·汤普森

@Paul Qt的QString :: format将四舍五入。如果那很关键,您将不得不四舍五入,或者检查输出“ 360”并用您自己的值替换它。
jfh

38

fmod(x, y) 是您使用的功能。


5

fmod()从中使用<cmath>。如果您不想包括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);

3
为什么不想包含C头文件?那就是它的目的。
基思·汤普森

2

您可以实现自己的模数函数来为您执行此操作:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.