我最近遇到了一个问题,使用模数除法可以很容易地解决这个问题,但是输入是一个浮点数:
给定一个周期函数(例如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)
9条答案
按热度按时间px9o7tmv1#
因为“余数”的正常数学概念仅适用于整数除法,即生成整数商所需的除法。
为了将“余数”的概念扩展到真实的,您必须引入一种新的“混合”运算,它将为 * 实数 * 操作数生成 * 整数 * 商。Core C语言不支持这种运算,但它作为标准库
fmod
函数提供。以及C99中的remainder
函数(注意这些函数并不相同,有一些特殊性,特别是它们不遵循整数除法的舍入规则)。ma8fv8wu2#
你要找的是fmod()。
我想更具体地回答你的问题,在旧的语言中,
%
运算符只是被定义为整数模除,而在新的语言中,他们决定扩展运算符的定义。**编辑:**如果让我猜一猜为什么,我会说这是因为模算术的思想起源于数论,专门处理整数。
nxowjjhe3#
我不能肯定地说,但我猜这主要是历史原因。相当多早期的C编译器根本不支持浮点。浮点是后来添加的,即使那时也不完全--主要是添加了数据类型,以及语言支持的“最”原始操作,但其他一切都留给了标准库。
sh7euo9m4#
C和C++中的模运算符
%
是为两个整数定义的,但是,有一个fmod()
函数可用于双精度数。i7uq4tfw5#
标准中的约束条件如下:
C11(ISO/IEC 9899:201 x)§6.5.5 * 乘法运算符 *
每个操作数都应该是算术类型。%运算符的操作数应该是整数类型。
C++11(ISO/IEC 14882 - 2011)§5.6 * 乘法运算符 *
解决方案是使用
fmod
,这正是%
的操作数首先被限制为整数类型的原因,根据C99 Rationale §6.5.5 * 乘法运算符 *:C89委员会拒绝将% operator扩展到浮动类型,因为这样的使用会重复fmod提供的功能
vi4fp9gy6#
尝试
fmod
lf5gs5x27#
模运算的数学概念也适用于浮点值,这是唐纳德·克努特在他的经典著作《计算机编程的艺术》(第一卷)中讨论的第一个问题。也就是说,它曾经是基础知识。
浮点取模运算符定义如下:
如前所述,%运算符对浮点数的no-op似乎与标准相关。CRTL提供了'fmod',通常还提供了'remainder',以便对fp数执行%。这两者之间的区别在于它们如何处理中间的'iquot'舍入。
“remainder”使用舍入到最接近值,而“fmod”使用简单截断。
如果您编写自己的C++数值类,那么没有什么可以阻止您通过包含重载的运算符%来修改无操作遗留项。
致上
ulmd4ohb8#
当您试图查找两个类型都为
Float
或Double
的数字的余数时,%
运算符在C++中不起作用。因此,您可以尝试使用
math.h
/cmath.h
中的fmod
函数,或者使用以下代码行来避免使用该头文件:whhtz7ly9#
对于C/C++,这仅为整数运算定义。
Python的范围更广一些,它允许你得到一个浮点数的余数,即number被除以多少次后的余数: