为什么模数除法(%)仅适用于整数?

Rei*_*ica 75 c c++

我最近遇到了一个问题,可以使用模数除法轻松解决,但输入是一个浮点数:

给定周期函数(例如sin)和只能在周期范围内计算它的计算机函数(例如[-π,π]),创建一个可以处理任何输入的函数.

"明显"的解决方案是这样的:

#include <cmath>

float sin(float x){
    return limited_sin((x + M_PI) % (2 *M_PI) - M_PI);
}
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?我收到此错误:

error: invalid operands of types double and double to binary operator %
Run Code Online (Sandbox Code Playgroud)

有趣的是,它确实在Python中有效:

def sin(x):
    return limited_sin((x + math.pi) % (2 * math.pi) - math.pi)
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 72

因为"余数"的正常数学概念仅适用于整数除法.即生成整数商所需的除法.

为了将"余数"的概念扩展为实数,您必须引入一种新的"混合"运算,它将为实际操作数生成整数商.Core C语言不支持此类操作,但它作为标准库函数提供,以及C99中的函数.(注意,这些函数不一样,并且有一些特殊性.特别是,它们不遵循整数除法的舍入规则.)fmodremainder

  • ** - 1**Re"正常的数学概念"余数"仅适用于整数除法",模运算的数学概念也适用于浮点值,这是Donald Knuth讨论的第一个问题之一在他的经典*计算机编程艺术*(第一卷).即它曾经是基本知识.今天,学生不接受他们支付的教育,恕我直言. (14认同)
  • 值得一提的是,根据98标准中%的定义:"(a/b)*b + a%b等于a." 对于浮点类型,`(a/b)*b`​​已经等于'a` [只要可以为浮点类型做出这样的声明],所以`a%b`永远不会特别有用. (7认同)
  • @Dennis:您可以通过要求"floor(a/b)*b + a%b = a"轻松修复此公式.注意,对于整数,floor(a/b)= a/b. (7认同)

Dou*_*hen 48

你正在寻找fmod().

我想更具体地回答你的问题,在较旧的语言中,%运算符只是定义为整数模块划分,在较新的语言中,他们决定扩展运算符的定义.

编辑: 如果我打算猜测为什么,我会说这是因为模运算的思想起源于数论并专门处理整数.

  • "旧语言" - APL可以追溯到1960年代,它的模运算符"|" 适用于整数和浮点数据(也包括标量,向量,矩阵,张量......).如果与浮点数一起使用,C的"%"模运算符无法执行与fmod相同的功能,这是没有充分理由的. (8认同)
  • @harper - 由于 C 包含浮点算术,例如加、减、乘和除,使用与整数相同的语法,我不明白为什么它不能包含使用相同语法的模数 (%) 。选择包含或不包含它似乎是任意的。 (2认同)

Jer*_*fin 15

我不能肯定地说,但我猜它主要是历史性的.相当多的早期C编译器根本不支持浮点数.它后来被添加,甚至还没有完全添加 - 主要是添加了数据类型,以及语言支持的原始操作,但其他一切都留给了标准库.


Mar*_*iot 12

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

  • 这是OP问题的答案,但忽略了OP试图做的基本问题:`sin(fmod(x,3.14))`或者`sin(fmod(x,M_PI))`不等于` sin(x)`表示'x`的大值.实际上,这些值可能差异达到2.0. (4认同)
  • @R ..:是的,但这是一个不同的问题,我不完全确定有一个公认的答案,尽管有很多[关于这个问题的研究](http://scholar.google.com/scholar?hl=en&q =与+大+输入+参数的周期+ + +功能的+评估+ btnG =搜寻和as_sdt = 1%2C21&as_ylo =&as_vis = 0) (2认同)

Yu *_*Hao 7

限制在标准中:

C11(ISO/IEC 9899:201x)§6.5.5 乘法运算符

每个操作数都应具有算术类型.%运算符的操作数应具有整数类型.

C++ 11(ISO/IEC 14882:2011)§5.6 乘法运算符

*和/的操作数应具有算术或枚举类型; %的操作数应具有整数或枚举类型.通常的算术转换是在操作数上执行的,并确定结果的类型.

的解决方案是使用fmod,这也正是为什么的操作数%被限制在第一位置为整数类型,根据C99理由 §6.5.5 乘法运算符:

C89委员会拒绝扩展%运营商以处理浮动类型,因为此类使用将复制fmod提供的设施