任何人都可以解释或提出一个解决方法,解释为什么当我在Python 3中舍入小数并且上下文设置为舍入一半时,它将舍入2.5到2,而在Python 2中它正确舍入为3:
Python 3.4.3和3.5.2:
>>> import decimal
>>> context = decimal.getcontext()
>>> context.rounding = decimal.ROUND_HALF_UP
>>> round(decimal.Decimal('2.5'))
2
>>> decimal.Decimal('2.5').__round__()
2
>>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
Decimal('3')
Python 2.7.6:
>>> import decimal
>>> context = decimal.getcontext()
>>> context.rounding = decimal.ROUND_HALF_UP
>>> round(decimal.Decimal('2.5'))
3.0
>>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
Decimal('3')
答案 0 :(得分:10)
请注意,当您致电round
时,您获得的是浮动值,而不是Decimal
。 round
正在将值强制转换为float,然后根据舍入浮点数的规则对其进行舍入。
如果您在调用ndigits
时使用可选的round()
参数,则会返回十进制结果,在这种情况下,它将按预期方式进行。
Python 3.4.1 (default, Sep 24 2015, 20:41:10)
[GCC 4.9.2 20150212 (Red Hat 4.9.2-6)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import decimal
>>> context = decimal.getcontext()
>>> context.rounding = decimal.ROUND_HALF_UP
>>> round(decimal.Decimal('2.5'), 0)
Decimal('3')
我还没有找到记录round(someDecimal)
返回int但round(someDecimal, ndigits)
返回小数的地方,但这似乎是Python 3.3及更高版本中发生的情况。在Python 2.7中,当你调用round()
时,你总是得到一个浮点数,但Python 3.3改进了Decimal
与Python内置函数的集成。
正如评论中所述,round()
委托给Decimal.__round__()
并确实表现出同样的行为:
>>> Decimal('2.5').__round__()
2
>>> Decimal('2.5').__round__(0)
Decimal('3')
我注意到Fraction
的文档说:
__round__()
__round__(ndigits)
The first version returns the nearest int to self, rounding half to even.
The second version rounds self to the nearest multiple of Fraction(1, 10**ndigits)
(logically, if ndigits is negative), again rounding half toward even.
This method can also be accessed through the round() function.
因此行为是一致的,因为没有参数它会改变结果的类型并将一半舍入到偶数,但似乎Decimal
无法记录其__round__
方法的行为。 / p>
编辑注意Barry Hurley在评论中说,round()
被记录为在没有可选参数和"浮点值"的情况下调用时返回int
。如果给出可选参数。 https://docs.python.org/3/library/functions.html#round
答案 1 :(得分:2)
扩展@Duncan的回答,round
内置函数在python 2和python 3之间改变,以舍入到最接近的偶数(这是统计中的标准)。
Python2文档:
...如果两个倍数相等,则完成舍入 从0开始(例如,round(0.5)为1.0,round(-0.5)为-1.0)。
Python3文档:
...如果两个倍数相等,则向均匀方向进行舍入 选择(例如,圆形(0.5)和圆形(-0.5)都是0,和 圆(1.5)是2)
如果round
没有为float
提供任何参数,则ndigits
会转换为round
,因此float
的行为与{D}}相同会>>> round(2.5)
2
>>> round(2.500000001)
3
>>> round(3.5)
4
s。
示例(在python3中):
function login()
{
var username = commandData[0];
var password = commandData[1];
$.post('../ajax/login.php', {username: username, password: password}, function(result) {
if (result.error)
writeTerminalLine(result.error);
else
$.post('../ajax/set-session.php', {key: 'member-id', value: result.member_id});
});
}
答案 2 :(得分:1)
这是Python 2与3中round
的舍入模式与从Python Decimal
重新实现C
之间的变化组合(参见&# 34; Features for 3.3 section PEP 398中的其他最终大规模变更" 。
对于round
,舍入策略已更改,如What's New In Python 3.0中所示[另请参阅Python 3.x rounding behavior]。此外,Python round
中的3
首先尝试为传递的对象定义的find an appropriate __round__
方法:
>>> round('1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type str doesn't define __round__ method
在Python 2.x
中,它首先尝试coerce it specifically to a float
然后围绕它:
>>> round('1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: a float is required
对于Decimal
,在Python 2
中,实现甚至缺少要调用的__round__
方法:
>>> Decimal.__round__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'Decimal' has no attribute '__round__'
因此,在round
个对象上调用Decimal
将其强制转换为float
得到rounded using _Py_double_round
;这导致float
始终返回,无论是否提供ndigits
的值。 decimal
在2.x
的纯Python中实现,而3
用3.2
实现({?}}。
In Python 3.3
it got shinny new __round__
method因为它已在C
中重新实施:
>>> Decimal.__round__
<method '__round__' of 'decimal.Decimal' objects>
现在,当round
被调用时,它会被round(<Decimal_object>)
选中。
如果参数PyDec_Round
不是,则使用默认上下文(C
)映射到ROUND_HALF_EVEN
中的ndigits
,现在为returns a PyLong(整数)提供,如果是,则在其上调用quantize
并返回一个新的舍入Decimal
对象。