User: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'>

计算结果的类型[编辑 | 编辑源代码]

Python 在进行计算时,会先将所有数字转化成可能需要的、最“通用”的类型。浮点数比整数通用,复数比浮点数通用。比如:

  1. 当整数和整数进行计算时,结果一般是两者之间最通用的类型:整数;
  2. 当整数和浮点数进行计算时,结果一定是两者之间最通用的类型:浮点数;
  3. 当整数和复数进行计算时,结果一定是两者之间最通用的类型:复数。

以上内容只有两个例外,就是:

  1. 整数和整数之间的除法一定会返回浮点数。
  2. 整数的负整数次幂会返回浮点数。

除法[编辑 | 编辑源代码]

扩展(选学)
这与许多其他语言不一致。有些编程语言在遇到除数为零时会返回“无穷大”或“NaN”。但和其他语言一样, Python 的浮点数也提供了无穷大和NaN。

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

无穷大与NaN(选学)[编辑 | 编辑源代码]

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")等方式也是可以的。

除一般的计算之外。无穷大的运算遵循以下法则:

  1. 无穷大和零作乘法,结果为NaN。
  2. 正无穷大和负无穷大作加法,结果为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, y)[编辑 | 编辑源代码]

此函数也会返回一类带余除法的余数。

% 运算符不同,math.fmod 返回的余数、和被除数 x 的符号相同。

在被除数远小于除数时,这种方法的精度比 % 运算要高。因为:

import math
print(math.fmod(-1e-100,1e100))  #结果为:-1e-100
print(-1e-100 % 1e100)        #结果为:1e100-1e-100,并舍入为:1e100

所以,作浮点数带余除法时,更推荐使用 math.fmod 而不是 %

math.remainder(x, y)[编辑 | 编辑源代码]

此函数也会返回一类不同的带余除法的余数。

与上述的两种运算不同,这种方法对商有规定:它会将 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)

math模块[编辑 | 编辑源代码]

除以上运算符之外,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 提供了几种简单的函数,可以利用已有对象,创建对应的的数字对象。

创建整数对象[编辑 | 编辑源代码]

提示
在对应Python文档中,有形如“如果 x 定义了 __int__()”的描述。该部分内容及类似内容的详细解释,将在之后的类与Python的运算中讲解。

函数int可以将内容转化为整数。比如:

print(int(1.23))      #结果:1
print(int(-1.23))     #结果:-1
print(int(" 1023")+1) #结果:1024
print(int(1))         #结果:1

int函数可以将浮点数或字符串转化为整数。如果把字符串转化为整数,被转化的字符串主要部分只能包含09以及+-,位于主要部分前后的空格和换行符\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函数[编辑 | 编辑源代码]

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表示(不区分大小写)。这种方法下,不支持前缀的0b0o0x

除此之外,如果向第二个参数输入0,则会根据字符串前缀的0b0o0x来判断进制,我们看以下示例。

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 中的浮点数,这种方法最多能保留二进制的52位有效数字。

对于一些在二进制中表示为无限循环小数的数字,比如十进制的0.1,在二进制下会表示为:0.0001100110011...,这不可避免地会产生截断,最终存储的数值只会是一个近似值。如果这些小误差通过加法等方式累计,可以导致一些显著的计算误差。

缩小或解决误差[编辑 | 编辑源代码]

round 函数[编辑 | 编辑源代码]

一个通用的解决方法是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"分别处理为1000001。相加之后为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

參考文獻[编辑 | 编辑源代码]