python-3.x 如何将浮点数0.5四舍五入到1.0,同时仍将0.45四舍五入到0.0,就像通常的学校四舍五入一样?

t2a7ltrp  于 2023-04-22  发布在  Python
关注(0)|答案(3)|浏览(178)

Python round(1 / 2)的默认值为0。
如何将浮点数0.5四舍五入到1.0,同时仍将0.45四舍五入到0.0,就像通常的学校四舍五入一样?

blmhpbnm

blmhpbnm1#

实际上,目前认为 * 不 * 盲目地将 *.5向上舍入是正确的。相反,将 *.5舍入到最接近的偶数是正确的。Python 3实现了这种“适当”的“银行家舍入”形式,但许多其他语言没有(然而)。盲目地四舍五入 *.5会产生轻微的偏差,但“银行家四舍五入”有助于平衡它。请参阅this thread了解更多信息。所以...

方法一

您可以有条件地使用ceil(...)函数(来自math module)。您必须有条件地执行此操作,以便对小于0.5的值也保持常规的舍入行为。请尝试以下操作(注意,这不是非常健壮的,因为它只适用于正值...它应该能够很容易地适应正值和负值):

import math

val = 1.5
x = 0

if (float(val) % 1) >= 0.5:
    x = math.ceil(val)
else:
    x = round(val)

注意ceil(...)函数将返回一个整数,而不是一个浮点数。这应该不是一个大问题,但现在你知道了。

方法二

从我上面链接的帖子来看,似乎还有一个选择是使用decimal模块来模拟“旧”的舍入方式。我有点复制和粘贴,但在这里你可以:

import decimal

x = decimal.Decimal('1.5').quantize(decimal.Decimal('1'), 
rounding=decimal.ROUND_HALF_UP)

假设舍入的decimal.ROUND_HALF_UP形式是你要找的。这样你就不必有条件地使用ceil(...)函数。

qij5mzcb

qij5mzcb2#

得到“学校”舍入,从0开始舍入中间的值,也可以用于负数,可以使用下面的函数。这也是Python 2中的舍入。

def round_school(x):
    i, f = divmod(x, 1)
    return int(i + ((f >= 0.5) if (x > 0) else (f > 0.5)))

一些示例结果:

1.50:  2
 1.49:  1

 0.50:  1
 0.49:  0

-0.49:  0
-0.50: -1

-1.49: -1
-1.50: -2
avwztpqn

avwztpqn3#

总是四舍五入

decimal

from decimal import Decimal, ROUND_HALF_UP

def round(number, ndigits=None):
    """Always round off"""
    exp = Decimal('1.{}'.format(ndigits * '0')) if ndigits else Decimal('1')
    return type(number)(Decimal(number).quantize(exp, ROUND_HALF_UP))

print(round(4.115, 2), type(round(4.115, 2)))
print(round(4.116, 2), type(round(4.116, 2)))
print(round(4.125, 2), type(round(4.125, 2)))
print(round(4.126, 2), type(round(4.126, 2)))
print(round(2.5), type(round(2.5)))
print(round(3.5), type(round(3.5)))
print(round(5), type(round(5)))
print(round(6), type(round(6)))
# 4.12 <class 'float'>
# 4.12 <class 'float'>
# 4.13 <class 'float'>
# 4.13 <class 'float'>
# 3.0 <class 'float'>
# 4.0 <class 'float'>
# 5 <class 'int'>
# 6 <class 'int'>

math

import math

def round(number, ndigits=0):
    """Always round off"""
    exp = number * 10 ** ndigits
    if abs(exp) - abs(math.floor(exp)) < 0.5:
        return type(number)(math.floor(exp) / 10 ** ndigits)
    return type(number)(math.ceil(exp) / 10 ** ndigits)

print(round(4.115, 2), type(round(4.115, 2)))
print(round(4.116, 2), type(round(4.116, 2)))
print(round(4.125, 2), type(round(4.125, 2)))
print(round(4.126, 2), type(round(4.126, 2)))
print(round(2.5), type(round(2.5)))
print(round(3.5), type(round(3.5)))
print(round(5), type(round(5)))
print(round(6), type(round(6)))
# 4.12 <class 'float'>
# 4.12 <class 'float'>
# 4.13 <class 'float'>
# 4.13 <class 'float'>
# 3.0 <class 'float'>
# 4.0 <class 'float'>
# 5 <class 'int'>
# 6 <class 'int'>

对比

import math
from timeit import timeit
from decimal import Decimal, ROUND_HALF_UP

def round1(number, ndigits=None):
    exp = Decimal('1.{}'.format(ndigits * '0')) if ndigits else Decimal('1')
    return type(number)(Decimal(number).quantize(exp, ROUND_HALF_UP))

def round2(number, ndigits=0):
    exp = number * 10 ** ndigits
    if abs(exp) - abs(math.floor(exp)) < 0.5:
        return type(number)(math.floor(exp) / 10 ** ndigits)
    return type(number)(math.ceil(exp) / 10 ** ndigits)

print(timeit('round1(123456789.1223456789, 5)', globals=globals()))
print(timeit('round2(123456789.1223456789, 5)', globals=globals()))
# 1.9912803000000001
# 1.2140076999999998

math的速度更快。

相关问题