Python中的模运算符

54

下面这段代码中的模运算符是什么意思?

from math import *
3.14 % 2 * pi

如何对浮点数进行取模运算?

5个回答

67

当你有这个表达式:

a % b = c

它实际上意味着存在一个整数n,使得c尽可能小,但非负。

a - n*b = c

手动计算时,您可以一遍又一遍地减去2(如果您的数字为负数,则加上2),直到最终结果是最小的正数为止:

  3.14 % 2
= 3.14 - 1 * 2
= 1.14

此外,3.14 % 2 * pi会被解释为(3.14 % 2) * pi。我不确定你是否打算写成3.14 % (2 * pi)(在任何一种情况下,算法是相同的。只需不断减少/增加,直到数字尽可能小)。


3
我更喜欢解释 x%y 等于 x - (math.floor(x/y)*y) ,这与您所说的相同,但在我看来更易理解。 - sabbahillel
@sabbahillel 这就是为什么在Python3中(-123) % 10 == 7,而在其他编程语言如C++中,结果是-3的原因。因为(-123) - (math.floor(-123/10)*10) == 7 - very hit
@veryhit 你知道Python源代码中定义%的参考文献在哪里吗?是不是cPython中定义%的方式不同?我知道有关math.fmod方法的文档,但我想知道本地%运算符的定义。 - MNCODE
1
@MNCODE:在CPython中,这是它的定义方式: https://github.com/python/cpython/blob/0301c9bdd1ebd788d1334cf3fe06c48f35bab0dc/Objects/floatobject.c#L587-L615 - Blender

26
除了其他的答案之外,fmod文档对此问题有些有趣的解释:

math.fmod(x, y)

返回由平台C库定义的fmod(x, y)。注意,Python表达式x % y可能不会返回相同的结果。C标准的目的是使fmod(x, y)在数学上(无限精度)等于x - n*y,其中n为某个整数,使得结果与x具有相同的符号并且其大小小于abs(y)。 Python的x % y返回具有y符号的结果,并且对于浮点参数可能无法准确计算。例如,fmod(-1e-100, 1e100)-1e-100,但Python的-1e-100 % 1e100的结果是1e100-1e-100,无法以浮点形式准确表示,四舍五入为令人惊讶的1e100。因此,在使用浮点数时通常优先使用fmod()函数,而在使用整数时则优先使用Python的x % y


1
我以前不知道 fmod。谢谢! - Blender

3

同普通的取模一样,您可以期望得到相同的结果。例如:7 % 4 = 37.3 % 4.0 = 3.3

但要注意浮点数精度问题。


2

与普通取模运算相同,3.14 % 6.28 = 3.14,就像3.14%4 =3.143.14%2 = 1.14一样(余数...)


@MadPhysicist 什么?取模运算的优先级与幂运算相同...肯定小于等于...那问题在哪里? - Joran Beasley
1
百分号(%)的优先级与除号(/)相同,但肯定小于幂运算(和乘法一样)。3.14 % 2 * pi 等同于 (3.14 % 2) * pi == 1.14 * pi 而不是 3.14 % (2 * pi) - Mad Physicist
我的答案中没有任何的乘除操作... 如果有的话,我可能会用括号来分组... 我不是完全确定你在说什么。哦,我现在明白了... 在原问题中不太清楚 OP 想要哪些括号,但 3.14 % (2*pi) 仍然是 3.14,这正是我所举的一个小于3.14的数来说明的例子... 据我所知,这个问题并不是关于运算顺序的,但无所谓了。 - Joran Beasley
好的,我现在无法取消踩了,不过你解释后答案确实有道理。 - Mad Physicist

1

你应该使用fmod(a,b)

虽然在数学上 abs(x%y) < abs(y) 是正确的,但是对于 floats 来说,由于 roundoff 的原因,它可能在数值上不正确。

例如,假设一个平台上的 Python float 是一个 IEEE 754 双精度数字,在计算 -1e-100 % 1e100 使其与 1e100 具有相同的符号,结果为 -1e-100 + 1e100,这在数值上完全等于 1e100

函数 fmod() 在 math 模块中返回一个结果,其符号与第一个参数的符号匹配,因此在这种情况下返回 -1e-100。哪种方法更合适取决于应用程序。

当 x = a%b 用于整数模数时


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接