geekdoc-python-zh/docs/pythoncentral/how-to-round-numbers-in-pyt...

8.6 KiB
Raw Permalink Blame History

如何在 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”中的数字就会变成一个整数。

如果你以前处理过数字舍入,很有可能你会这样处理:

  1. 通过将 n 的小数点移动 p 位将数字“n”四舍五入到“p”位。n 中的值乘以 10 p 得到值“m”
  2. 然后你看 m 的第一位小数。假设这个数是“d”如果“d”小于 5你把 m 向下取整;否则,你就围捕我。
  3. 最后,你将 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 |

截断算法的作用如下:

  1. 你提供的数字乘以 1000。这将小数点向右移动三位。
  2. 新数的整数部分用 int()取。
  3. 这个数字除以 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()函数是快速舍入数字的一个很好的方法。但是请记住,对数据的影响是极端的。

如果在大型数据集中使用这些函数,数据集可能会变得非常不精确。精度的降低会极大地改变使用数据进行的计算。