处理数字是编程的重要组成部分,尤其是在科学应用或处理货币价值时。
在这里,Python 中对数字进行四舍五入的需求变得至关重要。它允许我们将数字调整到附近的值,通常是为了降低其复杂性或使其达到一定的精度。让我们深入探讨如何在 Python 中执行此操作。
使用内置 round() 函数
Python 的内置round()
函数是对数字进行四舍五入的最简单方法。当数字恰好位于两个整数的中间时,它总是将数字四舍五入到最接近的偶数。
让我们看看这个函数如何处理整数、浮点数和复数。
# Integer
num = 5
print(round(num))
# Float
num = 3.14159
print(round(num))
# Complex number
num = 3.5 + 4.5j
try:
print(round(num))
except TypeError as e:
print(e)
Output:
5
3
type complex doesn't define __round__ method
第一个示例返回 5,因为它已经是一个整数。在第二个示例中,浮点数 3.14159 向下舍入为最接近的整数,即 3。最后一个示例会导致 TypeError,因为round()
函数不支持复数。
将负数四舍五入到最接近的整数
The round()
函数还可以处理负数,将它们四舍五入到最接近的整数,就像处理正数一样。
这是一个例子:
num = -3.6
print(round(num))
Output:
-4
正如您所看到的,负数 -3.6 舍入为 -4,每个都向数轴上最接近的整数移动。
四舍五入到特定小数位
The round()
函数还可以采用附加参数来指示您希望数字四舍五入到的位数。
第二个参数指定您想要多少位小数。
它的工作原理如下:
num = 3.14159
# Round to 1 decimal place
print(round(num, 1))
# Round to 2 decimal places
print(round(num, 2))
# Round to 3 decimal places
print(round(num, 3))
Output:
3.1
3.14
3.142
在第一种情况下,数字四舍五入到最接近的小数点后一位数字,即 3.1。在第二种情况下,四舍五入到最接近的保留 2 位小数的数字,即 3.14。
在最后一种情况下,它四舍五入到最接近的小数点后 3 位数字,即 3.142。
使用 math.floor() 舍入
The math.floor()
Python 中的函数将数字向下舍入到最接近的整数,并在数轴上向左移动。这意味着它总是将数字向下舍入到其周围的两个数字中较小的一个。
让我们来说明一下:
import math
# Positive number
num = 3.6
print(math.floor(num))
# Negative number
num = -3.6
print(math.floor(num))
Output:
3
-4
此处,3.6 向下舍入为 3,即小于它的最接近的整数。但是,对于 -3.6,该函数舍入为 -4,因为 -4 在数轴上位于 -3.6 的左侧。
使用 math.ceil() 舍入
The math.ceil()
Python 中的函数相当于math.floor()
。它将数字四舍五入到最接近的整数,并将数字在数轴上向右移动。
这意味着它总是将数字向上舍入到其周围的两个数字中较大的一个。
这是一个例子:
import math
# Positive number
num = 3.6
print(math.ceil(num))
# Negative number
num = -3.6
print(math.ceil(num))
Output:
4
-3
在上面的示例中,3.6 向上舍入为 4,即比它大的最接近的整数。但是,对于 -3.6,该函数舍入为 -3,因为 -3 在数轴上位于 -3.6 的右侧。
创建自定义舍入函数
在Python中,您可以通过定义一个名为的特殊方法来指示类的舍入行为__round__
.
当内置的round()
函数用于类的实例。
为了便于说明,让我们创建一个类,CustomRoundNumber
,将数字四舍五入为零,这种方法也称为截断。这是与标准 Python 舍入行为不同的方法:
class CustomRoundNumber:
def __init__(self, value):
self.value = value
def __round__(self, n=None):
# if no precision is given, round to the nearest integer
if n is None:
return int(self.value)
# if precision is given, shift the decimal point to the right by the desired number of places
multiplier = 10 ** n
value = self.value * multiplier
# Round towards zero
result = int(value)
return result / multiplier
num = CustomRoundNumber(1.6789)
print(round(num, 2)) # 1.67
print(round(num)) # 1
Output:
1.67
1
在提供的代码中,我们定义了一个类CustomRoundNumber
with a __round__
方法。该方法的任务是实施向零回合的策略。
因此,当round()
调用该类的实例,__round__
调用方法向零舍入。
浮点表示和限制
虽然舍入非常有用,但重要的是要了解 Python(以及大多数编程语言)中的浮点数由于其二进制表示方式而存在局限性。
这是因为浮点数无法精确地表示为二进制分数。在 2 进制中,1/10 是无限重复的分数。
因此,在基数 2 中,1/10 变为 0.0001100110011001100110011001100110011001100110011…等等。因此,精度会丢失并且无法恢复。
这不是一个错误,而是计算机基本属性的结果,是每个使用浮点数的人都需要注意的问题。
不过,我们将在本教程后面使用 Decimal 类型来处理这个问题。
让我们看一个例子:
num = 0.1 + 0.1 + 0.1
print(num == 0.3)
# Correctly rounded version
num_rounded = round(num, 2)
print(num_rounded == 0.3)
Output:
False
True
在这里,由于 0.1 的二进制表示不精确,将三个 0.1 相加得到的数字并不完全是 0.3。实际上,它是 0.30000000000000004。
然而,当我们将结果四舍五入到小数点后两位时,与 0.3 的比较将返回 True。
使用十进制模块
The quantize()
方法从decimal
模块根据给定的舍入策略将数字舍入到固定的小数位数:
from decimal import *
num = Decimal('0.555')
# Define the decimal places
decimal_places = Decimal('0.00')
# Round towards infinity
print(num.quantize(decimal_places, rounding=ROUND_CEILING))
# Round towards zero
print(num.quantize(decimal_places, rounding=ROUND_DOWN))
# Round towards negative infinity
print(num.quantize(decimal_places, rounding=ROUND_FLOOR))
# Round towards nearest, ties go towards zero
print(num.quantize(decimal_places, rounding=ROUND_HALF_DOWN))
# Round towards nearest, ties go to nearest even number
print(num.quantize(decimal_places, rounding=ROUND_HALF_EVEN))
# Round towards nearest, ties go away from zero
print(num.quantize(decimal_places, rounding=ROUND_HALF_UP))
# Round away from zero
print(num.quantize(decimal_places, rounding=ROUND_UP))
Output:
0.56
0.55
0.55
0.55
0.56
0.56
0.56
在此示例中,quantize()
方法对小数进行四舍五入num
使用指定的舍入模式保留两位小数。正如您所看到的,不同的舍入策略会产生不同的结果。
Python Decimal类型用于处理精度
The Decimal
提供的类型decimal
模块表示具有用户可定义精度的十进制浮点数。
这可以帮助解决标准浮点表示形式出现的精度问题。
Decimal
可以精确地表示像0.1这样的数字,而不能精确地表示为二进制浮点数。
此外,Decimal
允许您控制数字的精度和舍入以满足您的需求。
以下是 Decimal 如何保持精度的示例:
from decimal import Decimal
# Using float
num_float = 0.1 + 0.1 + 0.1
print(num_float)
# Using Decimal
num_decimal = Decimal('0.1') + Decimal('0.1') + Decimal('0.1')
print(num_decimal)
Output:
0.30000000000000004
0.3
如上所示,使用Decimal
可以防止浮点数可能出现的精度错误。
Python 2 和 Python 3 round() 函数
在 Python 2 中,round()
函数遵循传统的回合一半远离零的策略 - 例如,round(0.5)
and round(-0.5)
两者都导致1.0
and -1.0
分别。
另一方面,Python 3 默认使用四舍五入策略(也称为银行家舍入),其中半值四舍五入到最接近的偶数。
所以,在 Python 3 中,round(0.5)
结果是0
and round(1.5)
in 2
.
将代码从 Python 2 移动到 Python 3 时,这种差异可能会导致意外结果。
何时使用每种舍入方法
在某些应用中,选择正确的舍入方法可能至关重要。以下是一般准则:
-
使用内置
round()
:对于一般用例,尤其是当您需要四舍五入到最接近的偶数时(银行家四舍五入)。
-
Use
math.floor()
and math.ceil()
:当您需要始终向下舍入(朝负无穷大)或向上舍入(朝正无穷大)时,无论小数部分如何。
-
使用自定义舍入函数:当您需要特定行为时,例如始终向零舍入或远离零,或任何自定义舍入。
-
Use the
decimal
module:当精度至关重要时,例如在金融或科学应用中。该模块还允许您定义精度并通过以下方式使用不同的舍入策略quantize()
method.
了解您的需求并选择最适合您的用例的舍入方法非常重要。
修复了小数点的浮动错误
我被指派去调查我工作的电信公司财务模块中的一个错误。客户报告其帐户余额存在微小差异,当数百万用户的总和达到这一点时,就成为一个重大问题。
我重点介绍了如何使用 Python 的 float 类型进行财务计算。浮点运算虽然高效,但由于其二进制分数表示形式,可能会引入较小的舍入误差。
数百万笔交易中的这些微小的舍入误差导致了差异。
我使用一个脚本测试了这个假设,该脚本使用 float 和 Decimal 类型执行相同的操作。该脚本证实了我的怀疑:浮点算术与十进制相比产生了细微的差异,导致了我们的差异。
在我们的财务计算中,我开始将 float 类型替换为 Decimal 类型,该类型来自 Decimal 模块。它提供精确的十进制浮点运算,非常适合金融交易。
F.A.Q
问:如何将数字四舍五入到最接近指定小数位数的数字?
答:Python 中的 round 函数可用于将数字四舍五入到指定位数。除了数字之外,您还应该传递第二个参数,表示您想要的小数位数。示例:round(1.6666, 2) 将返回 1.67。
问:如何在大型数据集中将每个数字四舍五入到最接近的整数?
答:如果您正在处理大型数据集中的多个数字(例如列表),则可以使用列表理解以及 Python 的内置舍入函数将每个数字四舍五入到最接近的整数。示例如下:[round(num) for num in list]
问:Python 中如何将数字向上舍入到数字上限?
答:Python 中的 math 模块提供了 math.ceil() 函数来始终对数字进行舍入。通过使用此函数,您可以将给定的数字向上舍入到上限,这意味着它总是将数字向上舍入。
问:将数字四舍五入到指定精度的最接近数字的策略是什么?
答:Python 的内置舍入函数遵循一种称为“舍入到最接近的偶数”的策略,该策略可用于以指定的精度对数字进行舍入。如果一个数字恰好位于另外两个数字的中间,则该数字将四舍五入到最接近的偶数。
问:Python 中数字舍入中向负无穷偏差舍入的舍入是什么?
答:Python 中的 math.floor() 函数在数字舍入中实现向负无穷大偏差舍入。这意味着它总是向下舍入到最接近的整数,而不管小数部分。
问:如何在 Python 中将数字向上舍入和向下舍入到最接近的整数?
答:要向上舍入,可以使用 math.ceil(),要向下舍入,可以使用 math.floor()。两者都是Python math 模块中的方法。例如,math.ceil(1.2) 将返回 2,math.floor(1.2) 将返回 1。
问:在 Python 中,我们如何才能始终将平局舍入到远离零的位置?
答:Python 中的标准 round() 函数向最接近的偶数选择舍入,但如果您希望始终从零舍入(即 1.5 舍入到 2,-1.5 舍入到 -2),您可以使用decimal 模块的 ROUND_HALF_UP方法。
进一步阅读
https://docs.python.org/3/library/functions.html#round
https://docs.python.org/3/library/math.html
https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize