用户:Xyy23330121/Python/数字
Python 具有三种数字对象:整数int
、浮点数float
和复数complex
,其中复数可以被认为是分别表示实部和虚部的两个浮点数组成的。浮点数可以简单理解为小数。
可以用以下方式给变量赋值。
a = 1 #整数 1
b = 1.0 #浮点数 1.0
c = 1 + 0j #复数 1.0+0j
通过type
函数,可以查阅变量的类型[1]。比如:
print(type(a),type(b),type(c))
,
为分隔,可以给支持多个参数的函数传入多个参数。print
函数就支持多个参数,它可以同时输出多个参数的内容,并以空格分隔[2]。
参数按顺序传入,比如
print("a","b")
和print("b","a")
输出的结果是不同的,即便传入了排列不同的相同参数。运行以上代码的结果为:
<class 'int'> <class 'float'> <class 'complex'>
一些基本运算符如下:
print(2 + 1, type(2 + 1)) # 加法运算,输出为:3 <class 'int'>
print(2 - 1, type(2 - 1)) # 减法运算,输出为:1 <class 'int'>
print(2 * 1, type(2 * 1)) # 乘法运算,输出为:2 <class 'int'>
print(2 / 1, type(2 / 1)) # 除法运算,输出为:2.0 <class 'float'>
print(2 ** 1, type(2 ** 1)) # 幂运算,输出为:2 <class 'int'>
print(2 // 1, type(2 // 1)) # 带余除法求商,输出为:2 <class 'int'>
print(2 % 1, type(2 % 1)) # 带余除法求余,输出为:0 <class 'int'>
print(divmod(2,1)) # 同时输出带余除法的商和余数
Python 在进行计算时,会先将所有数字转化成可能需要的、最“通用”的类型。浮点数比整数通用,复数比浮点数通用。比如:
- 当整数和整数进行计算时,结果一般是两者之间最通用的类型:整数;
- 当整数和浮点数进行计算时,结果一定是两者之间最通用的类型:浮点数;
- 当整数和复数进行计算时,结果一定是两者之间最通用的类型:复数。
以上内容只有两个例外,就是:
- 整数和整数之间的除法一定会返回浮点数。
- 整数的负整数次幂会返回浮点数。
Python 作除法时,除数不能为零。如果输入:
1 / 0
Python 会报告一个错误:
ZeroDivisionError: division by zero
abs
函数会返回数字的绝对值。对于复数而言,会返回复数的模。
print(abs(-2)) #输出:2
print(abs(2.0)) #输出:2.0
print(abs(3+4j)) #输出:5.0
从上述结果可以看出。对于整数求绝对值,会返回一个整数;对于浮点数或复数求绝对值,会返回一个浮点数。
对于复数,可以单独取出其实部和虚部。
c = 1 + 2.3j
print(c.real) #c.real会输出c的实部,此例为1.0
print(c.imag) #c.imag会输出c的虚部,此例为2.3
Python 允许创建无穷大或 NaN 。NaN 是 Not a Number 的简称。有些编程语言在遇到除数为零时会返回“无穷大”或“NaN”。但 Python 严格限制除数不能为零,所以这两个数字不能直接用除数为零的表达式生成。
可以用以下方法创建无穷大或 NaN :
a = float("inf") #创建正无穷。也可以用float("infinity")。
b = float("-inf") #创建负无穷。也可以用float("-infinity")
c = float("nan") #创建NaN。
其中的字符串大小写不敏感,以正无穷为例,写成float("InF")
或float("iNFinity")
等方式也是可以的。
除一般的计算之外。无穷大的运算遵循以下法则:
- 无穷大和零作乘法,结果为NaN。
- 正无穷大和负无穷大作加法,结果为NaN。
而NaN无论进行什么计算,结果均为NaN。
由于复数可以被认为是由两个浮点数组成的,复数和无穷大以及复数和NaN的计算,计算后得到的实部和虚部两个浮点数,也都分别满足以上性质。
特别的,NaN 在比较运算符的表现很奇怪:
inf, nan = float("inf"), float("nan")
res = inf * 0; print(res, res == nan) #输出:nan False
res = inf - inf; print(res, res == nan) #输出:nan False
整数的带余除法很好理解。浮点数的带余除法与整数的带余除法类似。
对于整数 和正整数 。存在唯一的一对整数 和 ,满足以下算式:
我们称 是商, 是余数。
对于被除数 或除数 之一为浮点数时而言,以上算式同样有效,不过需要把 也变成浮点数,而把 变成用浮点数表示的整数。我们看以下示例:
print(-1.0//0.3 , -1.0%0.3)
其输出为:
-4.0 0.19999999999999996
即带余除法的商为-4,用浮点数表示为-4.0
,而余数为0.2,由于计算精度的问题,输出为0.19999999999999996
。
Python 的 %
运算,在除数 b
为负数时,设置余数为负数。此时,算式改为:
此函数也会返回一类带余除法的余数。
与 %
运算符不同,math.fmod
返回的余数、和被除数 x
的符号相同。
在被除数远小于除数时,这种方法的精度比 %
运算要高。因为:
import math
print(math.fmod(-1e-100,1e100)) #结果为:-1e-100
print(-1e-100 % 1e100) #结果为:1e100-1e-100,并舍入为:1e100
所以,作浮点数带余除法时,更推荐使用 math.fmod
而不是 %
。
此函数也会返回一类不同的带余除法的余数。
与上述的两种运算不同,这种方法对商有规定:它会将 round(x/y)
设为商,然后再将 x - round(x/y) * y
设为余数。
这种带余除法,是 IEEE 754 风格的带余除法。
除简单的计算而言,Python 支持一些简便写法。
a = 0
a += 1 #等同于 a = a + 1
其中,+=
被称为是赋值运算符。类似的,其他运算也有赋值运算符。
a = 0
a += 4 #此时a = 4
print(a)
a -= 2 #此时a = 2
print(a)
a *= 12 #此时a = 24
print(a)
a /= 3 #此时a = 8.0
print(a)
a //= 2 #此时a = 4.0
print(a)
a %= 5 #此时a = 4.0
print(a)
a **= 0.5 #此时 a = 2.0
print(a)
除以上运算符之外,Python 还提供了一个内置的数学运算模块。该模块对浮点数和整数支持一些基本的运算。以下将简单介绍该模块当中一些常用的函数和变量。
import math
#取整
a, b = 1.5, -0.5
A, B = math.ceil(a), math.ceil(b) #math.ceil函数用于向上取整,会返回不小于其中数字的最小整数
print(A,B) #输出为:2, 0
A, B = math.floor(a), math.floor(b) #math.floor函数用于向下取整,会返回不大于其中数字的最大整数
print(A,B) #输出为:1, -1
A, B = math.tunc(a), math.trunc(b) #math.trunc函数用于向零取整,会去除数字的小数部分
print(A,B) #输出为:1, 0
#数学常量
print(math.e) #输出为:2.718281...
print(math.pi) #输出为:3.141592...
math 模块还提供了三角函数等多个实用函数。关于 math 模块中的其他函数和变量,请参阅 Python 文档,这里不再列出。在一些情况下,math 模块中的一些函数,其误差要比运算符要小。所以当需要高精度计算的时候,请多查阅 math 模块的文档,可能能发现精度更高的方法。
类似,还有 cmath 模块用于处理复数的一些运算,详情请参阅cmath模块的Python文档
Python 提供了几种简单的函数,可以利用已有对象,创建对应的的数字对象。
函数int
可以将内容转化为整数。比如:
print(int(1.23)) #结果:1
print(int(-1.23)) #结果:-1
print(int(" 1023")+1) #结果:1024
print(int(1)) #结果:1
int
函数可以将浮点数或字符串转化为整数。如果把字符串转化为整数,被转化的字符串主要部分只能包含0
至9
以及+
、-
,位于主要部分前后的空格和换行符\n
等会被忽略。对于浮点数,该函数输出的结果为向零取整的结果。
对于已经是整数的内容,int
函数会直接输出其自身。
如果输入的内容不符合要求,比如输入了复数或错误的字符串,程序会报错退出。
比如:int("1 23")
、int("1-23")
和int("1.23")
会报错:
ValueError: invalid literal for int() with base 10
而int(1+0j)
会报错:
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'complex'
float
函数可以将内容转化为浮点数。比如:
print(float(1)) #结果:1.0
print(float("1.23")) #结果:1.23
print(float("-123e-2")) #结果:-1.23
1.23e-4
的字符串,表示的是科学计数法 的意思。float
函数可以将整数或字符串转化为浮点数。如果要转化字符串,字符串除了可以为表示整数、小数的字符串,也可以是科学计数法表示的浮点数。
还有一些其他形式的字符串可以被float
函数转化。比如上面选学章节提到过的float("inf")
。
与int
函数相同,位于首尾的空格和换行符会被忽略。而且,如果输入的内容不符合要求,比如输入了复数或错误的字符串,程序会报错退出。
print(complex(1)) #结果:1.0+0.0j
print(complex("1.23")) #结果:1.23+0.0j
print(complex("-123e-2+1j")) #结果:-1.23+1.0j
转化为复数的complex
函数和转化为浮点数的float
函数是类似的。但是要注意,主要部分不能有空格。比如以下的代码会报错:
print(complex("-123e-2 + 1j"))
除上述方法之外,还可以输入两个整数或浮点数的参数来生成复数:
print(complex(1, 2)) #结果:1.0+2.0j
print(complex(1.1, 2.1)) #结果:1.1+2.1j
input
函数可以在程序运行时输入字符串内容。比如运行以下代码:
c = input()
print("输入的内容:",c)
在程序运行时,输入 aabbcc
并按回车后,程序会输出:
输入的内容: aabbcc
同时,input
函数还可以给出提示。比如:
c = input("请输入内容:")
print("输入的内容:",c)
在程序运行时,会先输出:
请输入内容:
此时,输入 aabbcc
并按回车后,程序会输出:
输入的内容: aabbcc
了解了以上内容后,作为练习,我们可以写一个运算浮点数加法的程序。
#!/usr/bin/python
# -*- coding: utf-8 -*-
a = float(input("请输入第 1 个数字:"))
b = float(input("请输入第 2 个数字:"))
print("两数字相加的结果为:",a+b)
以上程序可以缩写为:
#!/usr/bin/python
# -*- coding: utf-8 -*-
print("两数字相加的结果为:", float(input("请输入第 1 个数字:")) + float(input("请输入第 2 个数字:")))
整数对象可以按不同进制转化为字符串对象。比如:
a = 10
print(bin(a)) #二进制, 输出:0b1010
print(oct(a)) #八进制, 输出:0o12
print(hex(a)) #十六进制,输出:0xa
我们也可以通过这样的方式给整数赋值,比如:
a = 0b11 + 0o10 + 0xa
print(a) #3 + 8 + 10,输出21
之后在字符串章节,会介绍一些其它地有类似作用的方法。
int
函数在转化字符串时,还可以输入第二个参数。第二个参数表示进制,我们看以下示例:
a = int("10", 2) #2 进制,a的值为2
b = int("10", 3) #3 进制,b的值为3
c = int("10", 8) #8 进制,c的值为8
d = int("1A", 16) #16进制,d的值为26
e = int("z", 36) #36进制,e的值为35
print(a, b, c, d, e)
在这种方法下,可以支持2进制至36进制。在每一位中,0~9的数字可以用0
~9
表示,而10~35的数字可以用字母a
~z
表示(不区分大小写)。这种方法下,不支持前缀的0b
、0o
和0x
。
除此之外,如果向第二个参数输入0
,则会根据字符串前缀的0b
、0o
和0x
来判断进制,我们看以下示例。
a = int("10", 0) #没有前缀,输出 10
b = int("0b10", 0) #二进制, 输出 2
c = int("0o10", 0) #八进制, 输出 8
d = int("0x10", 0) #十六进制,输出 16
print(a, b, c, d)
但是要注意,向第二个参数输入0
的时候,输入十进制数字时,字符串中第一个字符不能为"0"
。比如,以下的代码会报错:
print(int("10", 0)) #没有前缀,输出 10
print(int("010", 0)) #报错
初学者可以先跳过这一章节。待读者参与到涉及数字精度的项目时,再进行查阅。
在 Python 中,只要电脑的可用内存足够大,你就能表示足够大的整数。这与许多其他语言是不同的。
※ 在 Python 2.x 的版本中并非如此,请注意。
我们在之前浮点数的带余除法中,已经注意到数字精度的问题。应输出0.2
的,由于计算精度的原因,输出为0.19999999999999996
。实际上,还有一个更简单的数字精度的例子:
print(0.1 + 0.2) #输出为:0.30000000000000004
造成以上结果的原因,是计算机表示浮点数的方式导致的。计算机会用IEEE 754标准中的双精度浮点数来表示 Python 中的浮点数,这种方法最多能保留二进制的53位有效数字。
对于一些在二进制中表示为无限循环小数的数字,比如十进制的0.1,在二进制下会表示为:0.0001100110011...,这不可避免地会产生截断,最终存储的数值只会是一个近似值。如果这些小误差通过加法等方式累计,可以导致一些显著的计算误差。
一个通用的解决方法是round
函数。
round(number, n)
函数会将数字按十进制舍入至小数点后n
位。比如:
print(round(0.1 + 0.2, 2)) #输出为:0.3
我们可以估计程序所需要的最大精度,或者估计计算产生的最大误差,来选择舍入的位数。
还有一些其他方法可以用于减少这类误差。比如有两个函数可以对列表中的元素进行求和。我们通过[0.1] * 10
生成由10个0.1
组成的列表,然后代入这两个函数中进行计算:
print(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1) #输出:0.9999999999999999
print(sum([0.1] * 10)) #输出:1.0
import math
print(math.fsum([0.1] * 10)) #输出:1.0
其中,math.fsum
函数精度一般更高,但耗时也更长。而sum
函数精度较低,但耗时较短。读者可以根据自身情况进行选择。
对于小数位数确定,且精度也确定的一些计算,比如货币的计算,可以使用整数来进行计算。比如,在加法程序中,如果我们要计算1000元+0.01元,可以用字符串的一些方法把"1000"
和"0.01"
分别处理为100000
和1
。相加之后为100001
,转化为字符串后,再用字符串的方法加入小数点,输出"1000.01"
。具体方法参见之后的字符串章节。
参见本教程第十八章节。建议初学者不要立刻去读第十八章节的内容。至少是在学习完第十六章节后,再学习第十八章节。
位运算只对整数有意义。以下是所有位运算的方式:
a=44 #0010 1100
b=56 #0011 1000
print(a&b) #按位 与 运算符,若两数在该位都为1,则为1
#0010 1000 即40
print(a|b) #按位 或 运算符,在该位有至少一个数字1,则为1
#0011 1100 即60
print(a^b) #按位 异或 运算符,若两数在该位不同则为1
#0001 0100 即20
print(~a) #按位 取反 运算符,该数0与1互换
#由于整数表示的原理,这等同于 -a-1
print(a<<2) #该数左移2位,即与(2**2)相乘
#1011 0000 即176
print(a>>1) #该数右移1位,即除以(2**1)并向下取整
#0001 0110 即22
- ↑ type函数的Python文档 https://docs.python.org/zh-cn/3.12/library/functions.html#type
- ↑ print函数的Python文档 https://docs.python.org/zh-cn/3.12/library/functions.html#print