1119 lines
33 KiB
Markdown
1119 lines
33 KiB
Markdown
# Python 中的数字
|
||
|
||
> 原文:<https://realpython.com/python-numbers/>
|
||
|
||
你不需要成为一个数学天才就能很好地编程。事实是,很少有程序员需要知道比基本代数更多的知识。当然,您需要了解多少数学知识取决于您正在开发的应用程序。一般来说,成为一名程序员所需的数学水平比你想象的要低。尽管数学和计算机编程并不像有些人认为的那样相关,但是数字是任何编程语言不可或缺的一部分,T2 Python T3 也不例外。
|
||
|
||
**在本教程中,您将学习如何:**
|
||
|
||
* 创建**整数**和**浮点数**
|
||
* **将数字**四舍五入到给定的小数位数
|
||
* 格式化并显示**字符串中的数字**
|
||
|
||
我们开始吧!
|
||
|
||
**注:**本教程改编自 [*Python 基础知识:Python 实用入门 3*](https://realpython.com/products/python-basics-book/) 中“数字与数学”一章。如果你更喜欢视频课程,那么看看 [Python 基础:数字和数学](https://realpython.com/courses/python-basics-numbers-and-math/)。
|
||
|
||
该书使用 Python 内置的 [IDLE](https://realpython.com/python-idle/) 编辑器来创建和编辑 Python 文件,并与 Python shell 进行交互,因此在本教程中,您将会看到对 IDLE 内置调试工具的引用。但是,从您选择的编辑器和环境中运行示例代码应该没有问题。
|
||
|
||
**免费奖励:** [掌握 Python 的 5 个想法](https://realpython.com/bonus/python-mastery-course/),这是一个面向 Python 开发者的免费课程,向您展示将 Python 技能提升到下一个水平所需的路线图和心态。
|
||
|
||
## 整数和浮点数
|
||
|
||
Python 有三种内置的数字[数据类型](https://realpython.com/python-data-types/):整数、浮点数和复数。在本节中,您将了解整数和浮点数,这是两种最常用的数字类型。你将在后面的章节[中学习复数。](#complex-numbers)
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
### 整数
|
||
|
||
一个**整数**是一个没有小数位的整数。例如,`1`是整数,而`1.0`不是。整数数据类型的名称是`int`,可以通过`type()`看到:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> type(1)
|
||
<class 'int'>
|
||
```
|
||
|
||
您可以通过键入所需的数字来创建一个整数。例如,下面将整数`25`赋给[变量](https://realpython.com/python-variables/) `num`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> num = 25
|
||
```
|
||
|
||
当你像这样创建一个整数时,值`25`被称为一个**整数字面量**,因为这个整数是直接输入到代码中的。
|
||
|
||
您可能已经熟悉如何使用`int()`将包含整数的字符串转化为数字。例如,以下代码将字符串`"25"`转换为整数`25`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> int("25")
|
||
25
|
||
```
|
||
|
||
`int("25")`不是整数文字,因为整数值是从字符串创建的。
|
||
|
||
当您手写大数字时,通常将数字分成三组,用逗号或小数点隔开。1000000 这个数字比 1000000 容易读得多。
|
||
|
||
在 Python 中,不能使用逗号对整数文字中的数字进行分组,但是可以使用下划线(`_`)。以下两种方法都是将一百万表示为整数的有效方法:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1000000
|
||
1000000
|
||
|
||
>>> 1_000_000
|
||
1000000
|
||
```
|
||
|
||
整数的大小没有限制,考虑到计算机的内存是有限的,这可能会令人惊讶。试着在 IDLE 的交互窗口中输入你能想到的最大数字。Python 处理起来没问题!
|
||
|
||
### 浮点数
|
||
|
||
一个**浮点数**,简称 **float** ,是一个带小数位的数。`1.0`是浮点数,`-2.75`也是。浮点数据类型的名称是`float`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> type(1.0)
|
||
<class 'float'>
|
||
```
|
||
|
||
像整数一样,浮点可以从**浮点文字**创建,或者通过用`float()`将字符串转换成浮点来创建:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> float("1.25")
|
||
1.25
|
||
```
|
||
|
||
有三种方法来表示浮点文字。以下每一项都创建一个值为一百万的浮点文字:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1000000.0
|
||
1000000.0
|
||
|
||
>>> 1_000_000.0
|
||
1000000.0
|
||
|
||
>>> 1e6
|
||
1000000.0
|
||
```
|
||
|
||
前两种方法类似于创建整数文字的两种技术。第三种方法使用符号 **E 创建一个浮点文字。**
|
||
|
||
**注:** E 记数法是**指数记数法**的简称。你可能见过计算器使用这种符号来表示太大而无法在屏幕上显示的数字。
|
||
|
||
要用 E 表示法编写浮点文字,请键入一个数字,后跟字母`e`,然后再键入另一个数字。Python 取`e`左边的数字,然后乘以`e`后的数字的`10`。所以`1e6`相当于 1×10⁶.
|
||
|
||
Python 还使用 E 符号来显示大浮点数:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 200000000000000000.0
|
||
2e+17
|
||
```
|
||
|
||
浮动值`200000000000000000.0`显示为`2e+17`。`+`符号表示指数`17`是正数。您也可以使用负数作为指数:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1e-4
|
||
0.0001
|
||
```
|
||
|
||
字面上的`1e-4`解释为`10`的`-4`次方,也就是 1/10000,或`0.0001`。
|
||
|
||
与整数不同,浮点数确实有一个最大值。最大浮点数取决于您的系统,但是像`2e400`这样的东西应该远远超出了大多数机器的能力。`2e400`是 2×10⁴⁰⁰,远远大于[宇宙中原子的总数](https://en.wikipedia.org/wiki/Observable_universe#Matter_content)!
|
||
|
||
当达到最大浮点数时,Python 返回一个特殊的浮点值,`inf`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 2e400
|
||
inf
|
||
```
|
||
|
||
`inf`代表无穷大,这仅仅意味着你试图创建的数字超出了你的计算机所允许的最大浮点值。`inf`的类型仍然是`float`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 2e400
|
||
>>> n
|
||
inf
|
||
>>> type(n)
|
||
<class 'float'>
|
||
```
|
||
|
||
Python 还使用了`-inf`,它代表负无穷大,代表一个负浮点数,超出了计算机上允许的最小浮点数:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> -2e400
|
||
-inf
|
||
```
|
||
|
||
作为一名程序员,你可能不会经常遇到`inf`和`-inf`,除非你经常与非常大的数字打交道。
|
||
|
||
**检查你的理解**
|
||
|
||
展开下面的方框,检查您的理解程度:
|
||
|
||
|
||
|
||
写一个程序,创建两个变量,`num1`和`num2`。`num1`和`num2`都应该被赋予整数文本`25000000`,一个写有下划线,一个没有。将`num1`和`num2`分别打印在两行上。
|
||
|
||
您可以展开下面的方框查看解决方案:
|
||
|
||
|
||
|
||
首先,将值`25000000`赋给`num1`,不带任何下划线:
|
||
|
||
```py
|
||
num1 = 25000000
|
||
```
|
||
|
||
接下来,在新的一行上,将值`25_000_000`赋给变量`num2`:
|
||
|
||
```py
|
||
num2 = 25_000_000
|
||
```
|
||
|
||
通过将每个变量传递给 [`print()`](https://realpython.com/python-print/) 的单独调用,在单独的行上打印两个变量:
|
||
|
||
```py
|
||
print(num1)
|
||
print(num2)
|
||
```
|
||
|
||
在输出中,您可以看到这两个数字是相同的:
|
||
|
||
```py
|
||
25000000
|
||
25000000
|
||
```
|
||
|
||
尽管这两个变量都被赋予了值`25000000`,但是使用下划线将数字分组使得人们更容易快速地计算出数字是多少。再也不用眯着眼睛盯着屏幕数零了!
|
||
|
||
当你准备好了,你可以进入下一部分。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
## 算术运算符和表达式
|
||
|
||
在这一节中,您将学习如何用 Python 对数字进行基本的算术运算,如加、减、乘、除。在这个过程中,您将学习一些用代码编写数学表达式的惯例。
|
||
|
||
### 加法
|
||
|
||
用`+`运算符进行加法运算:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1 + 2
|
||
3
|
||
```
|
||
|
||
`+`操作符两边的两个数叫做**操作数**。在上面的例子中,两个操作数都是整数,但是操作数不需要是相同的类型。
|
||
|
||
您可以将一个`int`添加到一个`float`中,没有问题:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1.0 + 2
|
||
3.0
|
||
```
|
||
|
||
注意`1.0 + 2`的结果是`3.0`,是一个`float`。任何时候一个`float`加到一个数上,结果就是另一个`float`。两个整数相加总会产生一个`int`。
|
||
|
||
**注意:** [PEP 8 推荐](http://pep8.org/#other-recommendations)用空格将两个操作数与一个运算符分开。
|
||
|
||
Python 可以很好地评估`1+1`,但是`1 + 1`是首选格式,因为它通常更容易阅读。这条经验法则适用于本节中的所有操作者。
|
||
|
||
### 减法
|
||
|
||
要减去两个数,只需在它们之间放一个`-`运算符:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1 - 1
|
||
0
|
||
|
||
>>> 5.0 - 3
|
||
2.0
|
||
```
|
||
|
||
就像两个整数相加,两个整数相减总会得到一个`int`。每当操作数之一是一个`float`,结果也是一个`float`。
|
||
|
||
`-`运算符也用于表示负数:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> -3
|
||
-3
|
||
```
|
||
|
||
您可以从另一个数字中减去一个负数,但正如您在下面看到的,这有时看起来会令人困惑:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1 - -3
|
||
4
|
||
|
||
>>> 1 --3
|
||
4
|
||
|
||
>>> 1- -3
|
||
4
|
||
|
||
>>> 1--3
|
||
4
|
||
```
|
||
|
||
在上面的四个例子中,第一个是最符合 PEP 8 的。也就是说,您可以用括号将`-3`括起来,这样可以更清楚地表明第二个`-`正在修改`3`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1 - (-3)
|
||
4
|
||
```
|
||
|
||
使用括号是一个好主意,因为它使您的代码更加明确。计算机执行代码,而人类阅读代码。任何能让你的代码更容易阅读和理解的方法都是好的。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
### 乘法运算
|
||
|
||
要将两个数相乘,请使用`*`运算符:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 3 * 3
|
||
9
|
||
|
||
>>> 2 * 8.0
|
||
16.0
|
||
```
|
||
|
||
你从乘法中得到的数的类型遵循与加法和减法相同的规则。两个整数相乘得到一个`int`,一个数乘以一个`float`得到一个`float`。
|
||
|
||
### 分部
|
||
|
||
`/`运算符用于将两个数相除:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 9 / 3
|
||
3.0
|
||
|
||
>>> 5.0 / 2
|
||
2.5
|
||
```
|
||
|
||
与加法、减法和乘法不同,使用`/`运算符的除法总是返回一个`float`。如果想确保两个数相除后得到的是一个整数,可以用`int()`来转换结果:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> int(9 / 3)
|
||
3
|
||
```
|
||
|
||
请记住,`int()`会丢弃数字的任何小数部分:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> int(5.0 / 2)
|
||
2
|
||
```
|
||
|
||
`5.0 / 2`返回浮点数`2.5`,`int(2.5)`返回去掉`.5`的整数`2`。
|
||
|
||
### 整数除法
|
||
|
||
如果编写`int(5.0 / 2)`对您来说似乎有点冗长,Python 提供了第二个除法运算符,称为**整数除法**运算符(`//`),也称为**地板除法**运算符:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 9 // 3
|
||
3
|
||
|
||
>>> 5.0 // 2
|
||
2.0
|
||
|
||
>>> -3 // 2
|
||
-2
|
||
```
|
||
|
||
`//`运算符首先将左边的数除以右边的数,然后向下舍入为整数。当其中一个数字为负时,这可能不会给出您期望的值。
|
||
|
||
例如,`-3 // 2`返回`-2`。首先,`-3`除以`2`得到`-1.5`。然后`-1.5`被向下舍入到`-2`。另一方面,`3 // 2`返回`1`,因为两个数字都是正数。
|
||
|
||
上面的例子还说明了当其中一个操作数是`float`时,`//`返回一个浮点数。这就是为什么`9 // 3`返回整数`3`,`5.0 // 2`返回`float` `2.0`。
|
||
|
||
让我们看看当你试图将一个数除以`0`时会发生什么:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1 / 0
|
||
Traceback (most recent call last):
|
||
File "<stdin>", line 1, in <module>
|
||
ZeroDivisionError: division by zero
|
||
```
|
||
|
||
Python 给你一个`ZeroDivisionError`,让你知道你刚刚试图打破宇宙的一个基本规则。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
### 指数
|
||
|
||
您可以使用`**`运算符对数字进行幂运算:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 2 ** 2
|
||
4
|
||
|
||
>>> 2 ** 3
|
||
8
|
||
|
||
>>> 2 ** 4
|
||
16
|
||
```
|
||
|
||
指数不一定是整数。它们也可以是浮动的:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 3 ** 1.5
|
||
5.196152422706632
|
||
|
||
>>> 9 ** 0.5
|
||
3.0
|
||
```
|
||
|
||
将一个数提升到`0.5`的幂与求平方根是一样的,但是请注意,即使`9`的平方根是一个整数,Python 也会返回`float`T3。
|
||
|
||
对于正操作数,如果两个操作数都是整数,则`**`运算符返回一个`int`,如果其中一个操作数是浮点数,则返回一个`float`。
|
||
|
||
您也可以将数字提升到负幂:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 2 ** -1
|
||
0.5
|
||
|
||
>>> 2 ** -2
|
||
0.25
|
||
```
|
||
|
||
一个数的负幂等于用这个数的正幂除`1`。所以,`2 ** -1`和`1 / (2 ** 1)`是一样的,和`1 / 2`,或者说`0.5`是一样的。同理,`2 ** -2`与`1 / (2 ** 2)`相同,T6 与`1 / 4`相同,或者说`0.25`。
|
||
|
||
### 模数运算符
|
||
|
||
`%`运算符,或**模数**,返回左操作数除以右操作数的余数:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 5 % 3
|
||
2
|
||
|
||
>>> 20 % 7
|
||
6
|
||
|
||
>>> 16 % 8
|
||
0
|
||
```
|
||
|
||
`3`用`2`的余数除`5`一次,所以`5 % 3`就是`2`。类似地,`7`用`6`的余数除以`20`两次。在最后一个例子中,`16`可以被`8`整除,所以`16 % 8`就是`0`。任何时候`%`左边的数被右边的数整除,结果都是`0`。
|
||
|
||
`%`最常见的用途之一是确定一个数是否能被另一个数整除。例如,一个数`n`是偶数当且仅当`n % 2`是`0`。你认为`1 % 0`会有什么回报?让我们试一试:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 1 % 0
|
||
Traceback (most recent call last):
|
||
File "<stdin>", line 1, in <module>
|
||
ZeroDivisionError: integer division or modulo by zero
|
||
```
|
||
|
||
这是有意义的,因为`1 % 0`给出了`1`除以`0`的余数。但是你不能用`0`除`1`,所以 Python 养了一个`ZeroDivisionError`。
|
||
|
||
**注意:**当你在 IDLE 的交互窗口中工作时,像`ZeroDivisionError`这样的错误不会造成太大的问题。显示错误并弹出新的提示,允许您继续编写代码。
|
||
|
||
然而,当 Python 在运行脚本时遇到错误,执行就会停止。换句话说,程序**崩溃了**。在 *Python 基础*的第 8 章,你将学习如何处理错误,这样你的程序就不会意外崩溃。
|
||
|
||
当您对负数使用`%`操作符时,事情变得有点棘手:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 5 % -3
|
||
-1
|
||
|
||
>>> -5 % 3
|
||
1
|
||
|
||
>>> -5 % -3
|
||
-2
|
||
```
|
||
|
||
虽然乍一看可能令人震惊,但这些结果是 Python 中定义良好的行为的产物。为了计算一个数`x`除以一个数`y`的余数`r`,Python 使用了等式`r = x - (y * (x // y))`。
|
||
|
||
比如要找`5 % -3`,Python 先找`(5 // -3)`。既然`5 / -3`大约是`-1.67`,那就意味着`5 // -3`是`-2`。现在 Python 将它乘以`-3`得到`6`。最后 Python 用`5`减去`6`得到`-1`。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
### 算术表达式
|
||
|
||
您可以组合运算符来形成复杂的表达式。一个**表达式**是数字、操作符和括号的组合,Python 可以计算,或者**对**求值,返回一个值。
|
||
|
||
下面是一些算术表达式的例子:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 2*3 - 1
|
||
5
|
||
|
||
>>> 4/2 + 2**3
|
||
10.0
|
||
|
||
>>> -1 + (-3*2 + 4)
|
||
-3
|
||
```
|
||
|
||
表达式求值的规则与日常算术中的规则相同。在学校里,你可能以操作顺序的名义学习了这些规则。
|
||
|
||
在一个表达式中,`*`、`/`、`//`和`%`运算符都具有相同的**优先级**或优先级,并且每个运算符的优先级都高于`+`和`-`运算符。这就是为什么`2*3 - 1`返回`5`而不是`4`。因为`*`的优先级高于`-`操作符,所以`2*3`首先被计算。
|
||
|
||
您可能会注意到,上一个示例中的表达式没有遵循在所有运算符的两边都加一个空格的规则。PEP 8 对复杂表达式中的空格做了如下说明:
|
||
|
||
> 如果使用不同优先级的操作符,考虑在优先级最低的操作符周围添加空格。用自己的判断;但是,永远不要使用一个以上的空格,并且在二元操作符的两边要有相同数量的空格。([来源](https://pep8.org/#other-recommendations))
|
||
|
||
另一个好的做法是使用括号来表示操作应该执行的顺序,即使括号不是必需的。例如,`(2 * 3) - 1`可能比 2*3 - 1 更清晰。
|
||
|
||
## 让 Python 骗你
|
||
|
||
你觉得`0.1 + 0.2`是什么?答案是`0.3`对吧?让我们看看 Python 对此有什么看法。在交互式窗口中尝试一下:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 0.1 + 0.2
|
||
0.30000000000000004
|
||
```
|
||
|
||
这真是。。。*差不多*对。这到底是怎么回事?这是 Python 中的 bug 吗?
|
||
|
||
不,这不是一个错误!是一个**浮点表示错误**,与 Python 无关。这与浮点数在计算机内存中的存储方式有关。
|
||
|
||
**注:**本教程改编自 [*Python 基础知识:Python 实用入门 3*](https://realpython.com/products/python-basics-book/) 中“数字与数学”一章。如果你喜欢你正在阅读的东西,那么一定要看看这本书的其余部分。
|
||
|
||
数字`0.1`可以表示为分数`1/10`。数字`0.1`和它的分数`1/10`都是十进制的**表示**,或者是以 10 为基数的**表示**。然而,计算机以二进制表示法存储浮点数,通常称为二进制表示法**。**
|
||
|
||
当用二进制表示时,十进制数`0.1`会发生一些熟悉但可能意想不到的事情。分数`1/3`没有有限小数表示。也就是说,`1/3 = 0.3333...`小数点后有无限多的 3。同样的事情也发生在二进制的分数`1/10`上。
|
||
|
||
`1/10`的二进制表示是以下无限重复的分数:
|
||
|
||
```py
|
||
0.00011001100110011001100110011...
|
||
```
|
||
|
||
计算机的内存是有限的,所以数字`0.1`必须存储为近似值,而不是其真实值。存储的近似值略高于实际值,如下所示:
|
||
|
||
```py
|
||
0.1000000000000000055511151231257827021181583404541015625
|
||
```
|
||
|
||
但是,您可能已经注意到,当要求打印`0.1`时,Python 会打印`0.1`,而不是上面的近似值:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> 0.1
|
||
0.1
|
||
```
|
||
|
||
Python 并不只是砍掉`0.1`的二进制表示中的数字。实际发生的事情稍微微妙一些。
|
||
|
||
因为`0.1`在二进制中的近似值只是一个近似值,完全有可能一个以上的十进制数具有相同的二进制近似值。
|
||
|
||
例如,`0.1`和`0.10000000000000001`都有相同的二进制近似值。Python 打印出共享近似值的最短十进制数。
|
||
|
||
这解释了为什么在本节的第一个例子中,`0.1 + 0.2`不等于`0.3`。Python 将`0.1`和`0.2`的二进制近似值相加,得到的数字是*而不是*的二进制近似值`0.3`。
|
||
|
||
如果这一切开始让你头晕,不要担心!除非你正在为金融或科学计算编写程序,否则你不需要担心浮点运算的不精确性。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
## 数学函数和数字方法
|
||
|
||
Python 有几个内置函数,可以用来处理数字。在本节中,您将了解三种最常见的:
|
||
|
||
1. **`round()`** ,用于将数字四舍五入到小数点后若干位数
|
||
2. **`abs()`** ,用于获取一个数的绝对值
|
||
3. **`pow()`** ,用于将一个数提升到某种幂
|
||
|
||
您还将了解一种可以用于浮点数的方法,以检查它们是否有整数值。
|
||
|
||
### 用`round()`和舍入数字
|
||
|
||
您可以使用`round()`将数字四舍五入为最接近的整数:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> round(2.3)
|
||
2
|
||
|
||
>>> round(2.7)
|
||
3
|
||
```
|
||
|
||
当数字以`.5`结尾时,`round()`会有一些意外的行为:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> round(2.5)
|
||
2
|
||
|
||
>>> round(3.5)
|
||
4
|
||
```
|
||
|
||
`2.5`向下舍入到`2`,`3.5`向上舍入到`4`。大多数人认为以`.5`结尾的数字会被四舍五入,所以让我们仔细看看这是怎么回事。
|
||
|
||
Python 3 根据一种叫做[的策略对数字进行舍入,舍入到偶数](https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest)。平局是最后一位数字是五的任何数字。`2.5`和`3.1415`是纽带,而`1.37`不是。
|
||
|
||
当您将平局四舍五入时,首先查看平局中最后一位数字左边的一位数字。如果那个数字是偶数,那么你就向下取整。如果数字是奇数,则向上取整。这就是为什么`2.5`向下舍入到`2`,`3.5`向上舍入到`4`。
|
||
|
||
**注:**舍入到偶数是 [IEEE](https://en.wikipedia.org/wiki/Institute_of_Electrical_and_Electronics_Engineers) (电气和电子工程师协会)推荐的浮点数舍入策略,因为它有助于限制舍入对涉及大量数字的运算的影响。
|
||
|
||
IEEE 维护着一个名为 IEEE 754 的标准,用于在计算机上处理浮点数。它于 1985 年出版,至今仍被硬件制造商普遍使用。
|
||
|
||
通过向`round()`传递第二个参数,可以将一个数字四舍五入到给定的小数位数:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> round(3.14159, 3)
|
||
3.142
|
||
|
||
>>> round(2.71828, 2)
|
||
2.72
|
||
```
|
||
|
||
数字`3.14159`四舍五入到小数点后三位得到`3.142`,数字`2.71828`四舍五入到小数点后两位得到`2.72`。
|
||
|
||
`round()`的第二个参数必须是整数。如果不是,那么 Python 会抛出一个`TypeError`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> round(2.65, 1.4)
|
||
Traceback (most recent call last):
|
||
File "<pyshell#0>", line 1, in <module>
|
||
round(2.65, 1.4)
|
||
TypeError: 'float' object cannot be interpreted as an integer
|
||
```
|
||
|
||
有时`round()`得不到完全正确的答案:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> # Expected value: 2.68
|
||
>>> round(2.675, 2)
|
||
2.67
|
||
```
|
||
|
||
`2.675`是一个平局,因为它正好位于数字`2.67`和`2.68`的中间。因为 Python 将平局舍入到最近的偶数,所以您会期望`round(2.675, 2)`返回`2.68`,但是它返回的是`2.67`。这个错误是浮点表示错误的结果,而不是`round()`中的 bug。
|
||
|
||
处理浮点数可能会令人沮丧,但这种沮丧并不是 Python 特有的。所有实现 IEEE 浮点标准的语言都有同样的问题,包括 C/C++、Java 和 JavaScript。
|
||
|
||
然而,在大多数情况下,浮点数遇到的小错误可以忽略不计,`round()`的结果非常有用。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
### 用`abs()` 求绝对值
|
||
|
||
一个数 *n* 的[绝对值](https://realpython.com/python-absolute-value/)如果 *n* 为正则为 *n* ,如果 *n* 为负则为- *n* 。比如`3`的绝对值是`3`,而`-5`的绝对值是`5`。
|
||
|
||
在 Python 中要得到一个数的绝对值,可以使用 [`abs()`](https://realpython.com/python-absolute-value/#using-the-built-in-abs-function-with-numbers) :
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> abs(3)
|
||
3
|
||
|
||
>>> abs(-5.0)
|
||
5.0
|
||
```
|
||
|
||
`abs()`总是返回与其参数类型相同的正数。也就是说,整数的绝对值永远是正整数,浮点数的绝对值永远是正浮点数。
|
||
|
||
### 用`pow()`和提高幂
|
||
|
||
前面,您已经学习了如何使用`**`运算符对一个数字进行幂运算。你也可以使用`pow()`来达到同样的效果。
|
||
|
||
`pow()`需要两个参数。第一个参数是基数**,或者要计算的幂,第二个参数是指数**,或者要计算的幂。***
|
||
|
||
***例如,下面使用`pow()`将`2`提升到指数`3`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> pow(2, 3)
|
||
8
|
||
```
|
||
|
||
就像使用`**`一样,`pow()`中的指数可以是负的:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> pow(2, -2)
|
||
0.25
|
||
```
|
||
|
||
那么,`**`和`pow()`有什么区别呢?
|
||
|
||
`pow()`函数接受可选的第三个参数,该参数计算第一个数字的第二次幂,然后对第三个数字取[模](https://realpython.com/python-modulo-operator/)。换句话说,`pow(x, y, z)`相当于`(x ** y) % z`。
|
||
|
||
这里有一个例子,其中`x = 2`、`y = 3`和`z = 2`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> pow(2, 3, 2)
|
||
0
|
||
```
|
||
|
||
首先,`2`被提升到`3`的幂以得到`8`。然后计算`8 % 2`,这是`0`,因为`2`除以`8`没有余数。
|
||
|
||
### 检查浮点数是否是整数
|
||
|
||
你可能熟悉[串法](https://realpython.com/python-strings/#built-in-string-methods),比如`.lower()`、`.upper()`、`.find()`。整数和浮点数也有方法。
|
||
|
||
数字方法不经常使用,但是有一种方法很有用。浮点数有一个`.is_integer()`方法,如果数字是**整数**——意味着它没有小数部分——则返回`True`,否则返回`False`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> num = 2.5
|
||
>>> num.is_integer()
|
||
False
|
||
|
||
>>> num = 2.0
|
||
>>> num.is_integer()
|
||
True
|
||
```
|
||
|
||
`.is_integer()`的一个用途是验证[用户输入](https://realpython.com/python-input-output/)。例如,如果您正在为一家比萨饼店编写一个在线订购应用程序,那么您会希望检查客户输入的比萨饼数量是否是一个整数。
|
||
|
||
`round()`、`abs()`和`pow()`函数是内置函数,这意味着您不必为了使用它们而导入任何东西。但是这三个函数仅仅触及了 Python 中处理数字的所有函数的表面。
|
||
|
||
要获得更多数学乐趣,请查看[Python 数学模块:你需要知道的一切](https://realpython.com/python-math-module/)!
|
||
|
||
**检查你的理解**
|
||
|
||
展开下面的方框,检查您的理解程度:
|
||
|
||
|
||
|
||
编写一个程序,要求用户输入一个数字,然后显示四舍五入到两位小数的数字。运行时,您程序应该如下所示:
|
||
|
||
```py
|
||
Enter a number: 5.432
|
||
5.432 rounded to 2 decimal places is 5.43
|
||
```
|
||
|
||
您可以展开下面的方框查看解决方案:
|
||
|
||
|
||
|
||
要获得用户的输入,请将提示传递给`input()`:
|
||
|
||
```py
|
||
user_input = input("Enter a number: ")
|
||
```
|
||
|
||
请注意提示字符串末尾的空格。这确保了用户开始键入时输入的文本和提示中的冒号之间有一个空格。
|
||
|
||
`input()`返回的值是一个字符串,所以在对数字进行舍入之前,需要将其转换为浮点数:
|
||
|
||
```py
|
||
num = float(user_input)
|
||
```
|
||
|
||
请记住,上面的代码假设字符串`user_input`确实包含一个数值,而不是任何其他类型的文本。
|
||
|
||
**注意:**如果`user_input`包含非数字文本,那么`ValueError`将被引发。查看 [Python 异常:介绍](https://realpython.com/python-exceptions/),了解如何处理这类错误的信息。
|
||
|
||
现在您可以使用`round()`将值四舍五入到两位小数:
|
||
|
||
```py
|
||
rounded_num = round(num, 2)
|
||
```
|
||
|
||
记住,`round()`的第一个参数应该是要舍入的数字。第二个参数是要舍入到的小数位数。
|
||
|
||
最后,您可以通过将`rounded_num`插入 f 字符串来打印输出:
|
||
|
||
```py
|
||
print(f"{num} rounded to 2 decimal places is {rounded_num}")
|
||
```
|
||
|
||
`round()`是一种很好的舍入值的方法,但是如果您只是为了显示它们而舍入值,那么您可以考虑使用下一节中描述的技术。
|
||
|
||
当你准备好了,你可以进入下一部分。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
## 以样式打印数字
|
||
|
||
向用户显示数字需要将数字插入字符串。您可以通过用花括号将分配给数字的变量括起来,用 f-strings 来实现这一点:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 7.125
|
||
>>> f"The value of n is {n}"
|
||
'The value of n is 7.125'
|
||
```
|
||
|
||
那些花括号支持一种简单的[格式化语言](https://docs.python.org/3/library/string.html#format-specification-mini-language),您可以用它来改变最终格式化字符串中值的外观。
|
||
|
||
例如,要将上面示例中的值`n`格式化为两位小数,请将 f 字符串中花括号的内容替换为`{n:.2f}`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 7.125
|
||
>>> f"The value of n is {n:.2f}"
|
||
'The value of n is 7.12'
|
||
```
|
||
|
||
变量`n`后面的冒号(`:`)表示其后的所有内容都是格式规范的一部分。在这个例子中,格式规范是`.2f`。
|
||
|
||
`.2f`中的`.2`将数字四舍五入到小数点后两位,`f`告诉 Python 将`n`显示为**定点数**。这意味着即使原始数字的小数位数更少,该数字也只显示两位小数。
|
||
|
||
当`n = 7.125`时,`{n:.2f}`的结果为`7.12`。就像使用`round()`一样,Python 在格式化字符串中的数字时会将结舍入为偶数。所以,如果你用`n = 7.126`代替`n = 7.125`,那么`{n:.2f}`的结果就是`7.13`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 7.126
|
||
>>> f"The value of n is {n:.2f}"
|
||
'The value of n is 7.13'
|
||
```
|
||
|
||
要四舍五入到一位小数,请用`.1`替换`.2`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 7.126
|
||
>>> f"The value of n is {n:.1f}"
|
||
'The value of n is 7.1'
|
||
```
|
||
|
||
当您将数字格式化为定点时,它总是以您指定的精确小数位数显示:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 1
|
||
>>> f"The value of n is {n:.2f}"
|
||
'The value of n is 1.00'
|
||
>>> f"The value of n is {n:.3f}"
|
||
'The value of n is 1.000'
|
||
```
|
||
|
||
您可以使用`,`选项插入逗号,以千为单位对大数的整数部分进行分组:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 1234567890
|
||
>>> f"The value of n is {n:,}"
|
||
'The value of n is 1,234,567,890'
|
||
```
|
||
|
||
要舍入到某个小数位数并按千分组,请在格式规范中将`,`放在`.`之前:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 1234.56
|
||
>>> f"The value of n is {n:,.2f}"
|
||
'The value of n is 1,234.56'
|
||
```
|
||
|
||
说明符`,.2f`对于显示货币值很有用:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> balance = 2000.0
|
||
>>> spent = 256.35
|
||
>>> remaining = balance - spent
|
||
|
||
>>> f"After spending ${spent:.2f}, I was left with ${remaining:,.2f}"
|
||
'After spending $256.35, I was left with $1,743.65'
|
||
```
|
||
|
||
另一个有用的选项是`%`,用于显示百分比。`%`选项将一个数字乘以`100`,并以定点格式显示,后跟一个百分号。
|
||
|
||
`%`选项应该总是在你的格式规范的末尾,你不能把它和`f`选项混在一起。例如,`.1%`将数字显示为精确到小数点后一位的百分比:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> ratio = 0.9
|
||
>>> f"Over {ratio:.1%} of Pythonistas say 'Real Python rocks!'"
|
||
"Over 90.0% of Pythonistas say 'Real Python rocks!'"
|
||
|
||
>>> # Display percentage with 2 decimal places
|
||
>>> f"Over {ratio:.2%} of Pythonistas say 'Real Python rocks!'"
|
||
"Over 90.00% of Pythonistas say 'Real Python rocks!'"
|
||
```
|
||
|
||
格式化迷你语言功能强大,范围广泛。您在这里只看到了基础知识。欲了解更多信息,请查看官方文档。
|
||
|
||
**检查你的理解**
|
||
|
||
展开下面的方框,检查您的理解程度:
|
||
|
||
|
||
|
||
将数字`150000`打印为货币,千位用逗号分组。货币应以两位小数显示,并以美元符号开头。
|
||
|
||
您可以展开下面的方框查看解决方案:
|
||
|
||
|
||
|
||
让我们一步一步地建立我们的 f 弦。
|
||
|
||
首先,显示没有任何格式的值`150000`的 f 字符串如下所示:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> f"{150000}"
|
||
150000
|
||
```
|
||
|
||
这可能看起来有点奇怪,但是它让您可以添加格式说明符。
|
||
|
||
为了确保该值显示为浮点数,请在数字`150000`后加一个冒号(`:`),后跟字母`f`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> f"{150000:f}"
|
||
'150000.000000'
|
||
```
|
||
|
||
默认情况下,Python 显示精确到六位小数的数字。货币应该只有两位小数精度,所以可以在`:`和`f`之间加上`.2`:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> f"{150000:.2f}"
|
||
'150000.00'
|
||
```
|
||
|
||
要显示由逗号分组的数字,请在冒号(`:`)和点(`.`)之间插入逗号(`,`):
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> f"{150000:,.2f}"
|
||
'150,000.00'
|
||
```
|
||
|
||
最后,在字符串的开头添加一个美元符号(`$`),表示该值以美元为单位:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> f"${150000:,.2f}"
|
||
'$150,000.00'
|
||
```
|
||
|
||
f 字符串只是格式化数字以供显示的一种方式。查看[更新的 Python 字符串格式技术指南](https://realpython.com/python-formatted-output/),了解更多在 Python 中格式化数字和其他文本的方法。
|
||
|
||
当你准备好了,你可以进入下一部分。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
## 复数
|
||
|
||
Python 是为数不多的为复数提供内置支持的编程语言之一。虽然复数不经常出现在科学计算和计算机图形领域之外,但 Python 对它们的支持是它的优势之一。
|
||
|
||
如果你曾经上过微积分或更高级的代数数学课,那么你可能记得复数是一个由两个不同部分组成的数:实数部分**和虚数部分**。***
|
||
|
||
*要用 Python 创建一个复数,只需写实部,然后是加号,最后是字母 *j* 的虚部:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n = 1 + 2j
|
||
```
|
||
|
||
当您检查`n`的值时,您会注意到 Python 用括号将数字括起来:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n
|
||
(1+2j)
|
||
```
|
||
|
||
这种约定有助于消除显示的输出可能表示字符串或数学表达式的任何混淆。
|
||
|
||
虚数有两个属性,`.real`和`.imag`,分别返回该数的实部和虚部:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n.real
|
||
1.0
|
||
|
||
>>> n.imag
|
||
2.0
|
||
```
|
||
|
||
注意,Python 将实部和虚部都作为浮点数返回,即使它们被指定为整数。
|
||
|
||
复数也有一个`.conjugate()`方法,它返回数字的复共轭:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> n.conjugate()
|
||
(1-2j)
|
||
```
|
||
|
||
对于任何一个复数,它的**共轭**都是实部相同,虚部绝对值相同但符号相反的复数。所以在这种情况下,`1 + 2j`的复共轭是`1 - 2j`。
|
||
|
||
`.real`和`.imag`属性不像`.conjugate()`那样需要括号。
|
||
|
||
`.conjugate()`方法是一个对复数执行操作的函数,而`.real`和`.imag`不执行任何操作——它们只是返回一些关于数字的信息。
|
||
|
||
方法和属性的区别是[面向对象编程](https://realpython.com/python3-object-oriented-programming/)的一个重要方面。
|
||
|
||
除了除法运算符(`//`)之外,所有处理浮点数和整数的算术运算符也可以处理复数。由于这不是高等数学教程,我们不会讨论复杂算术的机制。相反,下面是一些将复数与算术运算符结合使用的示例:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> a = 1 + 2j
|
||
>>> b = 3 - 4j
|
||
|
||
>>> a + b
|
||
(4-2j)
|
||
|
||
>>> a - b
|
||
(-2+6j)
|
||
|
||
>>> a * b
|
||
(11+2j)
|
||
|
||
>>> a ** b
|
||
(932.1391946432212+95.9465336603415j)
|
||
|
||
>>> a / b
|
||
(-0.2+0.4j)
|
||
|
||
>>> a // b
|
||
Traceback (most recent call last):
|
||
File "<stdin>", line 1, in <module>
|
||
TypeError: can't take floor of complex number.
|
||
```
|
||
|
||
有趣的是,虽然从数学的角度来看并不奇怪,`int`和`float`对象也有`.real`和`.imag`属性以及`.conjugate()`方法:
|
||
|
||
>>>
|
||
|
||
```py
|
||
>>> x = 42
|
||
>>> x.real
|
||
42
|
||
>>> x.imag
|
||
0
|
||
>>> x.conjugate()
|
||
42
|
||
|
||
>>> y = 3.14
|
||
>>> y.real
|
||
3.14
|
||
>>> y.imag
|
||
0.0
|
||
>>> y.conjugate()
|
||
3.14
|
||
```
|
||
|
||
对于浮点数和整数,`.real`和`.conjugate()`总是返回数字本身,`.imag`总是返回`0`。然而,需要注意的一点是,如果`n`是整数,那么`n.real`和`n.imag`返回一个整数,如果`n`是一个浮点数,那么`n.imag`返回一个浮点数。
|
||
|
||
现在你已经了解了复数的基本知识,你可能想知道你什么时候需要用到它们。如果你正在为 web 开发、数据科学或通用编程而学习 Python,事实是你可能永远都不需要使用复数。
|
||
|
||
另一方面,复数在科学计算和计算机图形学等领域非常重要。如果您曾经在这些领域工作过,那么您可能会发现 Python 对复数的内置支持非常有用。
|
||
|
||
[*Remove ads*](/account/join/)
|
||
|
||
## 结论:Python 中的数字
|
||
|
||
在本教程中,您学习了 Python 中使用数字的所有知识。您看到了有两种基本类型的数字——整数和浮点数 Python 还内置了对复数的支持。
|
||
|
||
**在本教程中,您学习了:**
|
||
|
||
* 如何使用 Python 的**算术运算符**对数字进行基本算术运算
|
||
* 如何使用 PEP 8 最佳实践编写**算术表达式**
|
||
* 什么是浮点数以及为什么它们不总是 100%准确
|
||
* 如何将**四舍五入成数字**与`round()`
|
||
* 什么是复数以及 Python 中如何支持它们
|
||
|
||
无论您对数字和数学的熟悉程度如何,现在都可以用 Python 代码执行各种计算了。您可以使用这些知识来解决您在编程生涯中会遇到的各种问题。
|
||
|
||
**注意:**如果你喜欢在这个例子中从 [*Python 基础知识:Python 3*](https://realpython.com/products/python-basics-book/) 实用介绍中所学到的东西,那么一定要看看本书的其余部分[。](https://realpython.com/products/python-basics-book/)
|
||
|
||
## 延伸阅读
|
||
|
||
有关 Python 中数字和数学的更多信息,请查看以下资源:
|
||
|
||
* [Python 中的基本数据类型](https://realpython.com/python-data-types/)
|
||
* [Python 数学模块:你需要知道的一切](https://realpython.com/python-math-module/)
|
||
* [如何在 Python 中舍入数字](https://realpython.com/python-rounding/)
|
||
* [Python 平方根函数](https://realpython.com/python-square-root-function/)**************** |