我最近遇到an issue,可以使用模数除法轻松解决,但输入是浮点数:
给定一个周期函数(例如
sin
)和一个只能在周期范围内计算它的计算机函数(例如[-π,π]),创建一个可以处理任何输入的函数。
“显而易见”的解决方案如下:
#include <cmath>
float sin(float x){
return limited_sin((x + M_PI) % (2 *M_PI) - M_PI);
}
为什么这不起作用?我收到这个错误:
error: invalid operands of types double and double to binary operator %
有趣的是,它在Python中有效:
def sin(x):
return limited_sin((x + math.pi) % (2 * math.pi) - math.pi)
答案 0 :(得分:72)
因为“余数”的正常数学概念仅适用于整数除法。即产生整数商所需的除法。
为了将“余数”的概念扩展为实数,您必须引入一种新的“混合”运算,它将为实际操作数生成整数商。 Core C语言不支持此类操作,但它作为标准库fmod
函数提供,以及C99中的remainder
函数。 (请注意,这些函数不一样,并且有一些特殊性。特别是,它们不遵循整数除法的舍入规则。)
答案 1 :(得分:47)
您正在寻找fmod()。
我想更具体地回答你的问题,在较旧的语言中,%
运算符只是定义为整数模块划分,而在较新的语言中,他们决定扩展运算符的定义。
编辑:如果我打算猜测为什么,我会说这是因为模数运算的思想起源于数论并专门处理整数。
答案 2 :(得分:15)
我不能说确定,但我猜它主要是历史性的。相当多的早期C编译器根本不支持浮点数。它是在稍后添加的,甚至不是完全添加的 - 主要是添加了数据类型,并且语言中支持大多数原语操作,但其他一切都留给了标准库。
答案 3 :(得分:12)
C和C ++中的模运算符%
是针对两个整数定义的,但有一个fmod()
函数可用于双精度。
答案 4 :(得分:7)
约束在标准中:
C11(ISO / IEC 9899:201x)§6.5.5乘法运算符
每个操作数都应具有算术类型。 %运算符的操作数应该是 有整数类型。
C ++ 11(ISO / IEC 14882:2011)§5.6乘法运算符
*和/的操作数应具有算术或枚举类型; %的操作数应具有整数或枚举 类型。通常的算术转换是在操作数上执行的,并确定结果的类型。
解决方案是使用fmod
,这正是%
的操作数首先限于整数类型的原因,根据C99 Rationale§6.5.5乘法运算符:
C89委员会拒绝延长%运营商以处理浮动类型,因为此类使用会复制fmod提供的设施
答案 5 :(得分:4)
尝试fmod
答案 6 :(得分:2)
%运算符为您提供数字的REMAINDER(模数的另一个名称)。对于C / C ++,这仅针对整数运算定义。 Python有点宽泛,允许你得到浮点数的余数,剩余的数字可以被分成多少次:
>>> 4 % math.pi
0.85840734641020688
>>> 4 - math.pi
0.85840734641020688
>>>
答案 7 :(得分:2)
当您尝试查找属于%
或Float
类型的两个数字的剩余部分时,Double
运算符在C ++中不起作用。
因此,您可以尝试使用fmod
/ math.h
中的cmath.h
函数,或者您可以使用这些代码行来避免使用该头文件:
float sin(float x) {
float temp;
temp = (x + M_PI) / ((2 *M_PI) - M_PI);
return limited_sin((x + M_PI) - ((2 *M_PI) - M_PI) * temp ));
}
答案 8 :(得分:0)
“模运算的数学概念适用于浮点 价值观,这也是Donald Knuth的第一个问题 在他的经典著作《计算机编程的艺术》(第一卷)中进行了讨论。 即曾经是基础知识。”
浮点模运算符定义如下:
m = num - iquot*den ; where iquot = int( num/den )
如所示,浮点数上的%运算符的无操作出现 与标准相关。 CRTL提供“ fmod”,通常是“剩余” 以及对fp编号执行%。这两个谎言的区别 他们如何处理中间的“ iquot”取整。
'remainder'使用最近舍入法,'fmod'使用简单的截断法。
如果您编写自己的C ++数字类,没有什么可以阻止您 通过包括重载运算符%来修改无操作传统。
最好的问候