Lev*_*von 157 python rounding python-3.x
我刚刚重新阅读Python 3.0中的新功能,它指出:
round()函数舍入策略和返回类型已更改.确切的中途情况现在四舍五入到最接近的偶数结果而不是零.(例如,round(2.5)现在返回2而不是3.)
和圆形文件:
对于支持round()的内置类型,值被舍入到10的最接近的倍数到幂减去n; 如果两个倍数相等,则向均匀选择进行舍入
所以,在v2.7.3下:
In [85]: round(2.5)
Out[85]: 3.0
In [86]: round(3.5)
Out[86]: 4.0
Run Code Online (Sandbox Code Playgroud)
正如我所料.但是,现在在v3.2.3下:
In [32]: round(2.5)
Out[32]: 2
In [33]: round(3.5)
Out[33]: 4
Run Code Online (Sandbox Code Playgroud)
这似乎是违反直觉的,与我对四舍五入的理解相反(并且必然会绊倒人).英语不是我的母语,但在我读到这篇文章之前,我以为我知道舍入的含义是什么: - /我确信在引入v3的时候一定有一些关于这个的讨论,但是我无法找到一个很好的理由我的搜索.
我在这里错过了什么?
更新:@ Li-aungYip的评论"银行家的舍入"给了我正确的搜索词/搜索关键字,我发现了这个问题:为什么.NET使用银行家的舍入作为默认值?所以我会仔细阅读.
kin*_*all 141
Python 3.0的方式现在被认为是标准的舍入方法,尽管有些语言实现还没有在公共汽车上.
简单的"始终为圆形0.5向上"技术导致对较高数字的轻微偏差.通过大量计算,这可能很重要.Python 3.0方法消除了这个问题.
常用的舍入方法不止一种.IEEE 754是浮点数学的国际标准,它定义了五种不同的舍入方法(Python 3.0使用的方法是默认方法).还有其他人.
这种行为并不像它应该的那样广为人知.如果我没记错的话,AppleScript是这种舍入方法的早期采用者.roundAppleScript中的命令实际上提供了几个选项,但是在IEEE 754中默认是round-towards-even.显然,执行round命令的工程师已经厌倦了所有请求"让它像我学到的那样工作"学校"他实现了这个:round 2.5 rounding as taught in school是一个有效的AppleScript命令.:-)
daw*_*awg 35
您可以使用Decimal模块控制Py3000中的舍入:
>>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'),
rounding=decimal.ROUND_HALF_UP)
>>> Decimal('4')
>>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'),
rounding=decimal.ROUND_HALF_EVEN)
>>> Decimal('2')
>>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'),
rounding=decimal.ROUND_HALF_DOWN)
>>> Decimal('3')
Run Code Online (Sandbox Code Playgroud)
小智 12
只是在这里添加一份文档中的重要说明:
https://docs.python.org/dev/library/functions.html#round
注意
round()对于浮点数的行为可能会令人惊讶:例如,round(2.675,2)给出2.67而不是预期的2.68.这不是一个错误:这是因为大多数小数部分不能完全表示为浮点数.有关详细信息,请参阅浮点运算:问题和限制.
因此,在Python 3.2中获得以下结果不要感到惊讶:
>>> round(0.25,1), round(0.35,1), round(0.45,1), round(0.55,1)
(0.2, 0.3, 0.5, 0.6)
>>> round(0.025,2), round(0.035,2), round(0.045,2), round(0.055,2)
(0.03, 0.04, 0.04, 0.06)
Run Code Online (Sandbox Code Playgroud)
Python 3.x 将 .5 值舍入到偶数的邻居
assert round(0.5) == 0
assert round(1.5) == 2
assert round(2.5) == 2
import decimal
assert decimal.Decimal('0.5').to_integral_value() == 0
assert decimal.Decimal('1.5').to_integral_value() == 2
assert decimal.Decimal('2.5').to_integral_value() == 2
Run Code Online (Sandbox Code Playgroud)
但是,如果需要,可以将小数舍入“返回”更改为始终向上舍入 0.5:
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
assert decimal.Decimal('0.5').to_integral_value() == 1
assert decimal.Decimal('1.5').to_integral_value() == 2
assert decimal.Decimal('2.5').to_integral_value() == 3
i = int(decimal.Decimal('2.5').to_integral_value()) # to get an int
assert i == 3
assert type(i) is int
Run Code Online (Sandbox Code Playgroud)
我最近也有这个问题。因此,我开发了一个python 3模块,该模块具有2个函数trueround()和trueround_precision(),这些函数可以解决此问题并提供相同的舍入行为,这些都是从小学开始使用的(而不是银行家的舍入)。这是模块。只需保存代码,然后将其复制或导入即可。注意:trueround_precision模块可以根据需要根据十进制模块中的ROUND_CEILING,ROUND_DOWN,ROUND_FLOOR,ROUND_HALF_DOWN,ROUND_HALF_EVEN,ROUND_HALF_UP,ROUND_UP和ROUND_05UP标志来更改舍入行为(有关更多信息,请参见模块文档)。对于下面的功能,请参阅文档字符串,或者将help(trueround)和help(trueround_precision)复制到解释器中以获取进一步的文档。
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
def trueround(number, places=0):
'''
trueround(number, places)
example:
>>> trueround(2.55, 1) == 2.6
True
uses standard functions with no import to give "normal" behavior to
rounding so that trueround(2.5) == 3, trueround(3.5) == 4,
trueround(4.5) == 5, etc. Use with caution, however. This still has
the same problem with floating point math. The return object will
be type int if places=0 or a float if places=>1.
number is the floating point number needed rounding
places is the number of decimal places to round to with '0' as the
default which will actually return our interger. Otherwise, a
floating point will be returned to the given decimal place.
Note: Use trueround_precision() if true precision with
floats is needed
GPL 2.0
copywrite by Narnie Harshoe <signupnarnie@gmail.com>
'''
place = 10**(places)
rounded = (int(number*place + 0.5if number>=0 else -0.5))/place
if rounded == int(rounded):
rounded = int(rounded)
return rounded
def trueround_precision(number, places=0, rounding=None):
'''
trueround_precision(number, places, rounding=ROUND_HALF_UP)
Uses true precision for floating numbers using the 'decimal' module in
python and assumes the module has already been imported before calling
this function. The return object is of type Decimal.
All rounding options are available from the decimal module including
ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
ROUND_HALF_UP, ROUND_UP, and ROUND_05UP.
examples:
>>> trueround(2.5, 0) == Decimal('3')
True
>>> trueround(2.5, 0, ROUND_DOWN) == Decimal('2')
True
number is a floating point number or a string type containing a number on
on which to be acted.
places is the number of decimal places to round to with '0' as the default.
Note: if type float is passed as the first argument to the function, it
will first be converted to a str type for correct rounding.
GPL 2.0
copywrite by Narnie Harshoe <signupnarnie@gmail.com>
'''
from decimal import Decimal as dec
from decimal import ROUND_HALF_UP
from decimal import ROUND_CEILING
from decimal import ROUND_DOWN
from decimal import ROUND_FLOOR
from decimal import ROUND_HALF_DOWN
from decimal import ROUND_HALF_EVEN
from decimal import ROUND_UP
from decimal import ROUND_05UP
if type(number) == type(float()):
number = str(number)
if rounding == None:
rounding = ROUND_HALF_UP
place = '1.'
for i in range(places):
place = ''.join([place, '0'])
return dec(number).quantize(dec(place), rounding=rounding)
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助,
纳妮
| 归档时间: |
|
| 查看次数: |
46122 次 |
| 最近记录: |