8.6 KiB
如何在 Python 中舍入数字:简单步骤
原文:https://www.pythoncentral.io/how-to-round-numbers-in-python-easy-steps/
Python 被认为是最容易学习的编程语言之一,拥有庞大的标准库。更不用说,它提供了以不同方式处理问题的灵活性。
典型的例子:四舍五入一个数字。
在 Python 中,有几种不同的方法可以舍入一个数字。在本文中,我们将从内置的 round()函数开始,探讨四种方法。
用 round()函数对数字进行舍入
在 Python 中,使用 round()函数是舍入数字的最直接的方法之一。它接受两个数字参数,“n”和“ndigits”
它处理这些输入,将保存在“n”中的数字舍入到“ndigits”默认情况下,“ndigits”参数的值为零。所以,如果你不给它任何值,“n”中的数字就会变成一个整数。
如果你以前处理过数字舍入,很有可能你会这样处理:
- 通过将 n 的小数点移动 p 位,将数字“n”四舍五入到“p”位。n 中的值乘以 10 p 得到值“m”
- 然后你看 m 的第一位小数。假设这个数是“d”,如果“d”小于 5,你把 m 向下取整;否则,你就围捕我。
- 最后,你将 m 除以 10 p ,将小数点后的 p 位移回。
这个算法非常简单。即使你通常不这样处理舍入,你也应该能够理解它。
它所做的只是取小数点后的最后一位数字,如果该数字小于 5,则向下取整。如果大于 5,算法将其向上取整。
这意味着如果你试图用这个算法来舍入 2.5,它会舍入到 3。但是如果你试图用它来舍入 1.64,它会被舍入到 1.6。
但是 round()函数不是这样工作的。
下面是当你试图用函数舍入 2.5 时会发生的情况。
>>> round(2.5)
2
令人惊讶,对吧?但是当你试图用同样的函数舍入 1.5 会发生什么呢?
>>> round(1.5)
2
这不是你所期望的。但是这些输出不会引起恐慌——您不必在 Python bug tracker 上提出问题。这是因为该方法被设计成以这种方式工作。
这是因为 Python 使用 IEEE 754 标准进行舍入。这种方法被称为“银行家舍入”,其背后的思想是将数字舍入到最接近的值,甚至是最不重要的数字。
如果你认为这种舍入策略不符合你的需要,在 Python 中还有其他三种方法可以舍入一个数字。
通过截断舍入数字
截断是舍入数字最简单的方法,但也是最原始的方法。截断背后的思想是给定位置之后的所有数字都被替换为零。
| 值 | 截断为 | 结果 | | 14。568 | 十位数 | 10 | | 14。568 | 一锅端 | 14 | | 14。568 | 十分之一位 | 14.5 | | 14。568 | 第百名 | 14.56 |
截断算法的作用如下:
- 你提供的数字乘以 1000。这将小数点向右移动三位。
- 新数的整数部分用 int()取。
- 这个数字除以 1000,将小数位向后移三位。
这个过程很容易概括——你要做的就是用 10 p 代替“1000”,用“p”表示要截断的小数位数。
下面是这个函数的样子:
def truncate(n, decimals=0):
multiplier = 10 ** decimals
return int(n * multiplier) / multiplier
这个 truncate()函数中的第二个参数默认为 0。如果没有传递第二个参数,函数将返回传递给它的数字的整数部分。
您可以使用正数和负数来使用此功能:
>>> truncate(12.5)
12.0
>>> truncate(-5.963, 1)
-5.9
>>> truncate(1.625, 2)
1.62
>>> truncate(125.6, -1)
120.0
>>> truncate(-1374.25, -3)
-1000.0
你可能已经注意到截断一个正数会导致四舍五入。另一方面,截断负数会导致四舍五入。
如果你正在编写的程序需要你特别地向上或向下舍入数字,你可以为这两种应用程序编写程序。
让我们来看看这些舍入方法是什么样子的。
四舍五入数字
将一个数向上舍入的想法是将它向上舍入到下一个更高的数,直到一个特定的位数。下面的表格总结了这一点:
| 值 | 截断为 | 结果 | | 14。568 | 十位数 | 20 | | 14。568 | 一锅端 | 15 | | 14。568 | 十分之一位 | 14.6 | | 14。568 | 第百名 | 14.57 |
在 Python 中,可以使用 math 模块中的 ceil()函数对数字进行四舍五入。您可能已经猜到,ceil()方法的名称来源于单词“ceiling”
数学术语上限描述的是大于或等于给定数字的最接近的整数。同理,小于或等于给定数字的最接近的整数就是它的底数。
你必须注意,位于两个整数之间的数本身并不是整数。更重要的是,两个区间的上限是两个区间中较大的一个。让我们用一个例子来回顾一下这个概念。
数字 2.2 位于 2 和 3 之间,所以它的地板是 2,天花板是 3。您可能知道 ceiling 函数的概念,它将每个数字映射到它的上限。
该函数也接受整数,将它们的上限映射到整数本身。Python 还提供了上限函数 math.ceil(),该函数返回大于或等于输入的最接近的整数。
>>> import math
>>> math.ceil(3.2)
4
>>> math.ceil(4)
4
>>> math.ceil(-0.7)
0
因此,这是一个优秀的内置 Python 函数,您可以使用它来舍入数字。但是你也可以选择编写自己的函数,比如:
def round_up(n, decimals=0):
multiplier = 10 ** decimals
return math.ceil(n * multiplier) / multiplier
这个 round_up()函数看起来很像 truncate()函数。这是因为它们的算法相当相似。
它将 n 中的小数点向右移动适当的位数。这是通过将 n 乘以 10 **小数来实现的。
使用 math.ceil()函数将导出的值向上舍入到最接近的整数。然后,程序通过将该值除以 10 **小数来将小数点向左移动。
大多数舍入数字的技术都有相似的步骤——小数点被移动,一些舍入方法被应用,然后小数点被移回。
这种舍入数字的模式非常流行,因为这是人类想出的舍入数字的最明显的心算方法。
这里有几个上舍入函数的实例:
>>> round_up(2.1)
3.0
>>> round_up(4.23, 1)
4.3
>>> round_up(7.543, 2)
7.55
同样值得注意的是,您可以向算法的“小数”部分传递一个负值,就像在 truncate()中一样。这是如何工作的:
>>> round_up(32.45, -1)
40.0
>>> round_up(1452, -2)
1500
当一个负数以这种方式传递给函数时,函数中写的第一个参数将其四舍五入到小数点左边适当的位数。
了解了这一点,您是否会好奇向 round_up()传递一个负值会做什么?
我们来看看:
>>> round_up(-1.5)
-1.0
在对数字进行舍入时,你可能会期望围绕零对称。这可能会让你认为就像 1.5 被舍入到 2 一样,-1.5 必须被舍入到-2.0。
你需要记住 math.ceil()函数是如何工作的,以便理解真实的结果。
这有助于记住向上取整和向下取整的区别。
想象一个从-5 到 5 的数字范围。向上舍入意味着值从左向右跳跃。相反,向下舍入意味着值从右向左跳跃。
向下舍入数字
向下舍入是向上舍入的反义词。
向下舍入一个数字的想法是将它舍入到下一个更小的数字,直到一个特定的位数。
下面的表格总结了这一点:
| 值 | 截断为 | 结果 | | 14。568 | 十位数 | 10 | | 14。568 | 一锅端 | 14 | | 14。568 | 十分之一位 | 14.5 | | 14。568 | 第百名 | 14.56 |
在 Python 中向下舍入数字或多或少涉及 round_up()和 truncate()使用的相同算法。你移动小数点,四舍五入到整数,然后移回小数点。
Python 的好处在于标准库附带了 math.floor()方法,它的作用与 ceil()方法相反。在移动小数点后,它舍入到有问题的数字的下限。
>>> math.floor(2.2)
2
>>> math.floor(-1.5)
-2
现在让我们看看如何编写 round_down()函数:
def round_down(n, decimals=0):
multiplier = 10 ** decimals
return math.floor(n * multiplier) / multiplier
所以,你可以看到,这个程序和 round_up()程序是一样的,只是 math.ceil()被 math.floor()代替了。
让我们试着在 round_down()中放几个不同的值:
>>> round_down(2.5)
2
>>> round_down(3.37, 1)
3.3
>>> round_down(-0.7)
-1
编写一个 round_up()或 round_down()函数是快速舍入数字的一个很好的方法。但是请记住,对数据的影响是极端的。
如果在大型数据集中使用这些函数,数据集可能会变得非常不精确。精度的降低会极大地改变使用数据进行的计算。