Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python负十进制、十进制和正整数的模运算_Python_Python 3.x_Decimal - Fatal编程技术网

python负十进制、十进制和正整数的模运算

python负十进制、十进制和正整数的模运算,python,python-3.x,decimal,Python,Python 3.x,Decimal,使用简单的ints: >>> -45 % 360 315 鉴于,使用十进制.decimal: >>> from decimal import Decimal >>> Decimal('-45') % 360 Decimal('-45') 我希望得到十进制('315') 这有什么原因吗?是否有一种方法可以获得一致的行为(无需修补decimal.decimal)?(我没有改变上下文,也找不到如何改变上下文来解决这种情况)。经过长时间的搜索(因

使用简单的
int
s:

>>> -45 % 360
315
鉴于,使用
十进制.decimal

>>> from decimal import Decimal
>>> Decimal('-45') % 360
Decimal('-45')
我希望得到
十进制('315')

这有什么原因吗?是否有一种方法可以获得一致的行为(无需修补
decimal.decimal
)?(我没有改变上下文,也找不到如何改变上下文来解决这种情况)。

经过长时间的搜索(因为搜索“%”、“mod”、“modulo”等会得到上千个结果),我终于意外地发现:

十进制对象上的算术运算之间有一些小的差异 以及整数和浮点数的算术运算。当余数运算符% 应用于十进制对象时,结果的符号为 除数的符号,而不是除数的符号:

>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')

我不知道这样做的原因,但看起来不可能改变这种行为(不打补丁)。

Python的行为符合IBM的标准

定义如下:

余数取两个操作数;它返回整数除法的余数。[……]

结果是计算整除运算(如所述)后的被除数余数,必要时四舍五入为精确数字。如果结果的符号不为零,则与原始股息的符号相同

因此,因为
Decimal('-45')//D('360')
Decimal('-0')
,所以余数只能是
Decimal('-45')

为什么商是0而不是-1?报告说:

除以整数取两个操作数;它将两个数字相除并返回结果的整数部分。[……]

返回的结果定义为当股息大于或等于除数时,从股息中重复减去除数的结果。在这个减法过程中,使用了被除数和除数的绝对值:最终结果的符号与使用正常除法的结果相同。[……]

注:[……]

  • 定义除法整数和余数运算,以便将其作为标准运算(如上所述)的副产品进行计算。一旦整数结果可用,除法过程即结束;股息的剩余部分就是剩余部分
  • 你能从45减去360多少次?0次。是否有整数结果?它是。然后商是0,带负号,因为运算表明

    结果的符号是操作数符号的异或


    至于为什么十进制规范采用这种方法,而不是像在数学中那样,余数总是正的,我推测这可能是因为减法算法的简单性。计算商的绝对值不需要检查操作数的符号。无论如何,现代实现可能使用更复杂的算法,但在标准形成、硬件更简单(晶体管更少)的年代,简单性可能是一个重要因素。有趣的事实:英特尔仅在2007年发布时才从基数2整数除法转换为基数16。

    十进制是否使用
    math.fmod()
    ?他们都有相同的行为“因此,在处理浮点时,通常首选函数fmod(),而在处理整数时,则首选Python的x%y。”@Piintesky根据我在库源代码中的理解,它确实将数学作为_math导入,但是\u math仅用于从
    浮点
    构建一个
    十进制
    实例
    \uuuuMod\uuuuuuuuu
    (以及其他方法,如
    \uuuuuuTrueDiv\uuuuu
    )通过调用
    Decimal.\uDivide()
    计算商和余数,该方法依赖于调用整数的
    divmod
    。然而,它并没有产生相同的结果。。。请注意:
    divmod(-45360)=(-1315)
    但是
    divmod(十进制('-45')、十进制('360'))==(十进制('-0')、十进制('-45'))
    。我认为@Mr.T提到
    fmod是正确的。即使
    Decimal
    的实现根本不涉及
    fmod
    ,但其目的似乎至少是为了模拟
    fmod
    的行为。很抱歉进行了编辑。我原以为添加一个摘录就足以说明问题,但后来我发现它有点复杂,所以我添加了我自己的答案。你让它听起来像修补是一件极端的事情,需要避免,但像Python这样的语言在你自己的代码(子类、神奇的“dunder”方法、包装器等)中给了你很大的空间来做这件事。当然,你也可以做一些简单但有效的工作,编写你自己的函数来代替内置的语法。@JohnY对不起,我不是故意这么说的;我的意图是让问题不被理解为“如何修补Decimal以获得此类行为?”,而是“是否存在此类行为的原因?”以及“是否有任何已实施的方法来更改此行为(例如,通过上下文设置)?”。也许我应该提到我已经在需要的地方实现了一个小的变通方法。