c++ 为什么模数除法(%)只能用于整数?

6uxekuva  于 2022-12-27  发布在  其他
关注(0)|答案(9)|浏览(386)

我最近遇到了一个问题,使用模数除法可以很容易地解决这个问题,但是输入是一个浮点数:
给定一个周期函数(例如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)
px9o7tmv

px9o7tmv1#

因为“余数”的正常数学概念仅适用于整数除法,即生成整数商所需的除法。
为了将“余数”的概念扩展到真实的,您必须引入一种新的“混合”运算,它将为 * 实数 * 操作数生成 * 整数 * 商。Core C语言不支持这种运算,但它作为标准库fmod函数提供。以及C99中的remainder函数(注意这些函数并不相同,有一些特殊性,特别是它们不遵循整数除法的舍入规则)。

ma8fv8wu

ma8fv8wu2#

你要找的是fmod()
我想更具体地回答你的问题,在旧的语言中,%运算符只是被定义为整数模除,而在新的语言中,他们决定扩展运算符的定义。

**编辑:**如果让我猜一猜为什么,我会说这是因为模算术的思想起源于数论,专门处理整数。

nxowjjhe

nxowjjhe3#

我不能肯定地说,但我猜这主要是历史原因。相当多早期的C编译器根本不支持浮点。浮点是后来添加的,即使那时也不完全--主要是添加了数据类型,以及语言支持的“最”原始操作,但其他一切都留给了标准库。

sh7euo9m

sh7euo9m4#

C和C++中的模运算符%是为两个整数定义的,但是,有一个fmod()函数可用于双精度数。

i7uq4tfw

i7uq4tfw5#

标准中的约束条件如下:
C11(ISO/IEC 9899:201 x)§6.5.5 * 乘法运算符 *
每个操作数都应该是算术类型。%运算符的操作数应该是整数类型。
C++11(ISO/IEC 14882 - 2011)§5.6 * 乘法运算符 *

  • 和/的操作数应为算术或枚举类型; %的操作数应该是整数或枚举类型。2通常的算术转换是在操作数上执行的,并决定结果的类型。

解决方案是使用fmod,这正是%的操作数首先被限制为整数类型的原因,根据C99 Rationale §6.5.5 * 乘法运算符 *:
C89委员会拒绝将% operator扩展到浮动类型,因为这样的使用会重复fmod提供的功能

lf5gs5x2

lf5gs5x27#

模运算的数学概念也适用于浮点值,这是唐纳德·克努特在他的经典著作《计算机编程的艺术》(第一卷)中讨论的第一个问题。也就是说,它曾经是基础知识。
浮点取模运算符定义如下:

m = num - iquot*den ; where iquot = int( num/den )

如前所述,%运算符对浮点数的no-op似乎与标准相关。CRTL提供了'fmod',通常还提供了'remainder',以便对fp数执行%。这两者之间的区别在于它们如何处理中间的'iquot'舍入。
“remainder”使用舍入到最接近值,而“fmod”使用简单截断。
如果您编写自己的C++数值类,那么没有什么可以阻止您通过包含重载的运算符%来修改无操作遗留项。
致上

ulmd4ohb

ulmd4ohb8#

当您试图查找两个类型都为FloatDouble的数字的余数时,%运算符在C++中不起作用。
因此,您可以尝试使用math.h/cmath.h中的fmod函数,或者使用以下代码行来避免使用该头文件:

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));
}
whhtz7ly

whhtz7ly9#

对于C/C++,这仅为整数运算定义。
Python的范围更广一些,它允许你得到一个浮点数的余数,即number被除以多少次后的余数:

>>> 4 % math.pi
0.85840734641020688
>>> 4 - math.pi
0.85840734641020688
>>>

相关问题