改变Python数学模块对非正数除法的行为

5 投票
3 回答
559 浏览
提问于 2025-04-16 18:06

在C++和Python这两种编程语言中,处理非正数的除法是有很大不同的:

//c++:
11 / 3 = 3
11 % 3 = 2
(-11) / 3 = -3
(-11) % 3 = -2
11 / (-3) = -3
11 % (-3) = 2
(-11) / (-3) = 3
(-11) % (-3) = -2

从上面的例子可以看出,C++会让结果尽量小。而Python的表现则是这样的:

#python
11 / 3 = 3
11 % 3 = 2
(-11) / 3 = -4
(-11) % 3 = 1
11 / (-3) = -4
11 % (-3) = -1
(-11) / (-3) = 3
(-11) % (-3) = -2

我无法自己编写一个像C++那样的除法函数,因为我想用它来检查C++的计算器程序,而Python不支持中缀运算符。有没有简单的方法可以让Python在整数除法时表现得像C++呢?比如说,设置一个标志或者其他什么方式?

3 个回答

0

你还应该看看标准库里的decimal模块。

Decimal(十进制)“是基于一种浮点模型,这种模型是为了人类设计的,并且有一个重要的指导原则——计算机必须提供一种与人们在学校学习的算术运算方式相同的算术运算。”——摘自十进制算术规范。

不过,下面的结果是

import decimal
decimal.divmod(-11, 3)
>>> (-4, 1)
2

没有任何设置可以让Python的除法运算像C++那样工作。

你之前说过不能自己写除法函数,但如果你改变主意的话,可以这样做:

def cpp_int_div(dividend, divisor):
    a, b = dividend, divisor
    sign = 1 if (a>0 and b>0) or (a<0 and b<0) else -1
    return (abs(a)/abs(b)) * sign

def cpp_int_mod(dividend, divisor): # or just use math.fmod  (from Thomas K)
    a, b = dividend, divisor
    sign = 1 if a>0 else -1
    return (abs(a)%abs(b)) * sign

这段代码展示了它是按照你的要求来工作的:

print "11 / 3 = %d" % cpp_int_div(11,3)
print "11 %% 3 = %d" % cpp_int_mod(11,3)
print "(-11) / 3 = %d" % cpp_int_div(-11, 3)
print "(-11) %% 3 = %d" % cpp_int_mod(-11, 3)
print "11 / (-3) = %d" % cpp_int_div(11, -3)
print "11 %% (-3) = %d" % cpp_int_mod(11, -3)
print "(-11) / (-3) = %d" % cpp_int_div(-11, -3)
print "(-11) %% (-3) = %d" % cpp_int_mod(-11, -3)

这样会得到:

11 / 3 = 3
11 % 3 = 2
(-11) / 3 = -3
(-11) % 3 = -2
11 / (-3) = -3
11 % (-3) = 2
(-11) / (-3) = 3
(-11) % (-3) = -2
3

正如Thomas K所说,使用math.fmod来进行取模运算,或者如果你真的想的话,可以自己定义一个:

def cmod(x, y):
    return abs(x) % abs(y) * (1 if x > 0 else -1)

这个函数应该模拟C语言风格的除法:

def cdiv(x, y):
    return abs(x) / abs(y) * cmp(x, 0) * cmp(y, 0)

你提到你必须使用/%这两个运算符。其实这是不可能的,因为你不能重写内置运算符。不过,你可以定义自己的整数类型,并重载__div____mod__这两个运算符。

撰写回答