1.round
(number[, ndigits])
返回最近的 10^(-ndigits)的值,若又两个选择,取偶数值的。如:
round(0.5)
Out[22]: 0
round(-0.5)
Out[23]: 0
round(1.5)
Out[24]: 2
round(2.5)
Out[25]: 2
ndigits可取负值
>>> a = 1627731
>>> round(a, -1)
1627730
>>> round(a, -2)
1627700
>>> round(a, -3)
1628000
round的使用因为数值问题会有奇怪现象如: round(2.675,2)
得到2.67
i而不是 2.68。要想精确计算数值类,用Decimal对象。
2.format
(value[, format_spec])
该函数与round()取值方式一样。
>>> x = 1234.56789
>>> # Two decimal places of accuracy
>>> format(x, '0.2f')
'1234.57'
>>> # Right justified in 10 chars, one-digit accuracy
>>> format(x, '>10.1f')
' 1234.6'
>>> # Left justified
>>> format(x, '<10.1f')
'1234.6 '
>>> # Centered
>>> format(x, '^10.1f')
' 1234.6 '
>>> # Inclusion of thousands separator
>>> format(x, ',')
'1,234.56789'
>>> format(x, '0,.1f')
'1,234.6'
3.decimal模块
官方入口:https://docs.python.org/zh-cn/3.7/library/decimal.html#module-decimal
该模块的设计以三个概念为中心:decimal 数值,算术上下文和信号。
Context:decimal --- 十进制定点和浮点运算 — Python 3.7.12 文档
信号:decimal --- 十进制定点和浮点运算 — Python 3.7.12 文档
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,
InvalidOperation])
>>> Decimal("1.2")+Decimal("1.0")
Decimal('2.2')
>>> getcontext().prec = 7 # 修改精度,加减乘除看
>>>Decimal("1.2")+Decimal("1.0")
Decimal('2.2')
#临时上下文
with localcontext() as ctx:
ctx.prec = 42 # Perform a high precision calculation
s = calculate_something()
s = +s # Round the final result back to the default precision
#三种预置上下文和自定义上下文
>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857142857142857142857142857')
>>> ExtendedContext
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[], traps=[])
>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857143')
>>> Decimal(42) / Decimal(0)
Decimal('Infinity')
>>> setcontext(BasicContext)
>>> Decimal(42) / Decimal(0)
Traceback (most recent call last):
File "<pyshell#143>", line 1, in -toplevel-
Decimal(42) / Decimal(0)
DivisionByZero: x / 0
class decimal.
BasicContext
¶
这是由通用十进制算术规范描述所定义的标准上下文。 精度设为九。 舍入设为 ROUND_HALF_UP。 清除所有旗标。 启用所有陷阱(视为异常),但 Inexact, Rounded 和 Subnormal 除外。
由于启用了许多陷阱,此上下文适用于进行调试。
class decimal.
ExtendedContext
这是由通用十进制算术规范描述所定义的标准上下文。 精度设为九。 舍入设为 ROUND_HALF_EVEN。 清除所有旗标。 不启用任何陷阱(因此在计算期间不会引发异常)。
由于禁用了陷阱,此上下文适用于希望结果值为 NaN
或 Infinity
而不是引发异常的应用。 这允许应用在出现当其他情况下会中止程序的条件时仍能完成运行。
class decimal.
DefaultContext
此上下文被 Context 构造器用作新上下文的原型。 改变一个字段(例如精度)的效果将是改变 Context 构造器所创建的新上下文的默认值。
此上下文最适用于多线程环境。 在线程开始前改变一个字段具有设置全系统默认值的效果。 不推荐在线程开始后改变字段,因为这会要求线程同步避免竞争条件。
在单线程环境中,最好完全不使用此上下文。 而是简单地电显式创建上下文,具体如下所述。
默认值为 prec
=28
, rounding
=ROUND_HALF_EVEN,并为 Overflow, InvalidOperation 和 DivisionByZero 启用陷阱。
在已提供的三种上下文之外,还可以使用 Context 构造器创建新的上下文。
class decimal.
Context
(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)
创建一个新上下文。 如果某个字段未指定或为 None,则从 DefaultContext 拷贝默认值。 如果 flags 字段未指定或为 None,则清空所有旗标。
舍入模式
decimal.
ROUND_CEILING
舍入方向 Infinity
。
decimal.
ROUND_DOWN
舍入方向为零。
decimal.
ROUND_FLOOR
舍入方向为 -Infinity
。
decimal.
ROUND_HALF_DOWN
舍入到最接近的数,同样接近则舍入方向为零。
decimal.
ROUND_HALF_EVEN
舍入到最接近的数,同样接近则舍入到最接近的偶数。
decimal.
ROUND_HALF_UP
舍入到最接近的数,同样接近则舍入到零的反方向。
decimal.
ROUND_UP
舍入到零的反方向。
decimal.
ROUND_05UP
如果最后一位朝零的方向舍入后为 0 或 5 则舍入到零的反方向;否则舍入方向为零。
create_decimal
(num)
基于 num 创建一个新 Decimal 实例但使用 self 作为上下文。 与 Decimal 构造器不同,该上下文的精度、舍入方法、旗标和陷阱会被应用于转换过程。
quantize
(exp, rounding=None, context=None)
返回的值等于四舍五入的第一个运算数并且具有第二个操作数的指数。
>>> Decimal('1.41421356').quantize(Decimal('1.000'))
Decimal('1.414')
与其他运算不同,如果量化运算后的系数长度大于精度,那么会发出一个 InvalidOperation 信号。这保证了除非有一个错误情况,量化指数恒等于右手运算数的指数。
与其他运算不同,量化永不信号下溢,即使结果不正常且不精确。
如果第二个运算数的指数大于第一个运算数的指数那或许需要四舍五入。在这种情况下,舍入模式由给定 rounding
参数决定,其余的由给定 context
参数决定;如果参数都未给定,使用当前线程上下文的舍入模式。
每当结果的指数大于 Emax
或小于 Etiny
就会返回错误。
Q. 当我使用两个有效位的输入时,我要如何在一个应用中保持有效位不变?
A. 某些运算例如与整数相加、相减和相乘将会自动保留固定的小数位数。 其他运算,例如相除和非整数相乘则将会改变小数位数,需要再加上 quantize()
处理步骤:
>>> a = Decimal('102.72') # Initial fixed-point values
>>> b = Decimal('3.17')
>>> a + b # Addition preserves fixed-point
Decimal('105.89')
>>> a - b
Decimal('99.55')
>>> a * 42 # So does integer multiplication
Decimal('4314.24')
>>> (a * b).quantize(TWOPLACES) # Must quantize non-integer multiplication
Decimal('325.62')
>>> (b / a).quantize(TWOPLACES) # And quantize division
Decimal('0.03')
在开发定点数应用时,更方便的做法是定义处理 quantize()
步骤的函数:
>>> def mul(x, y, fp=TWOPLACES):
... return (x * y).quantize(fp)
>>> def div(x, y, fp=TWOPLACES):
... return (x / y).quantize(fp)
>>> mul(a, b) # Automatically preserve fixed-point
Decimal('325.62')
>>> div(b, a)
Decimal('0.03')
Q. 表示同一个值有许多方式。 数字 200
, 200.000
, 2E2
和 02E+4
的值都相同但有精度不同。 是否有办法将它们转换为一个可识别的规范值?
A. normalize()
方法可将所有相同的值映射为统一表示形式:
>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
>>> [v.normalize() for v in values]
[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]
Q. 有些十进制值总是被打印为指数表示形式。 是否有办法得到一个非指数表示形式?
A. 对于某些值来说,指数表示形式是表示系数中有效位的唯一办法。 例如,将 5.0E+3
表示为 5000
可以让值保持恒定,但是无法显示原本的两位有效数字。
如果一个应用不必关心追踪有效位,则可以很容易地移除指数和末尾的零,丢弃有效位但让值保持不变:
>>> def remove_exponent(d):
... return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')
4.二进制、八进制、十六进制
>>> x = 1234
>>> bin(x)
'0b10011010010'
>>> oct(x)
'0o2322'
>>> hex(x)
'0x4d2'
#不带0b、0o、0x
>>> format(x, 'b') # '{0:b}'.format(x)
'10011010010'
>>> format(x, 'o')# '{0:o}'.format(x)
'2322'
>>> format(x, 'x') # '{0:x}'.format(x)
'4d2'
#带符号
>>> x = -1234
>>> format(x, 'b')
'-10011010010'
>>> format(x, 'x')#
'-4d2'
#不带符号--32位
>>> x = -1234
>>> format(2**32 + x, 'b')
'11111111111111111111101100101110'
>>> format(2**32 + x, 'x')
'fffffb2e'
#转成整数
>>> int('4d2', 16)
1234
>>> int('10011010010', 2)
1234
5.无穷大、NaN
>>> a = float('inf')
>>> b = float('-inf')
>>> c = float('nan')
>>> math.isinf(a)
True
>>> math.isnan(c)
True
>>> a = float('inf')
>>> a + 45
inf
>>> a * 10
inf
>>> 10 / a
0.0
>>> a = float('inf')
>>> a/a
nan
>>> b = float('-inf')
>>> a + b
nan
>>> c = float('nan')
>>> c + 23
nan
>>> c / 2
nan
>>> c * 2
nan
>>> math.sqrt(c)
nan
>>> c = float('nan')
>>> d = float('nan')
>>> c == d
False
>>> c is d
False
6.分数
官方入口:fractions --- 分数 — Python 3.7.12 文档
>>> from fractions import Fraction
>>> a = Fraction(5, 4)
>>> b = Fraction(7, 16)
>>> print(a + b)
27/16
>>> print(a * b)
35/64
>>> # Converting a float to a fraction
>>> x = 3.75
>>> y = Fraction(*x.as_integer_ratio())
>>> y
Fraction(15, 4)
7.数组行数字操作,用numpy比list效率高很多,也会省很多存储空间
>>> # Python lists
>>> x = [1, 2, 3, 4]
>>> y = [5, 6, 7, 8]
>>> x * 2
[1, 2, 3, 4, 1, 2, 3, 4]
>>> x + 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list
>>> x + y
[1, 2, 3, 4, 5, 6, 7, 8]
>>> # Numpy arrays
>>> import numpy as np
>>> ax = np.array([1, 2, 3, 4])
>>> ay = np.array([5, 6, 7, 8])
>>> ax * 2
array([2, 4, 6, 8])
>>> ax + 10
array([11, 12, 13, 14])
>>> ax + ay
array([ 6, 8, 10, 12])
>>> ax * ay
array([ 5, 12, 21, 32])
8.线性代数用numpy.linalg
>>> import numpy.linalg
>>> # Determinantinant--行列式
>>> numpy.linalg.det(m)
-229.99999999999983
>>> # Eigenvalues--特征值
>>> numpy.linalg.eigvals(m)
array([-13.11474312, 2.75956154, 6.35518158])
>>> # Solve for x in mx = v--解方程
>>> x = numpy.linalg.solve(m, v)
>>> x
matrix([[ 0.96521739],
[ 0.17391304],
[ 0.46086957]])
>>> m * x
matrix([[ 2.],
[ 3.],
[ 4.]])
>>> v
matrix([[2],
[3],
[4]])
9.伪随机模块random
官方:random --- 生成伪随机数 — Python 3.7.12 文档
>>> import random
#随机挑选一个
>>> values = [1, 2, 3, 4, 5, 6]
>>> random.choice(values)
2
>>> random.choice(values)
3
#随机N个
>>> random.sample(values, 2)
[6, 2]
>>> random.sample(values, 3)
[5, 4, 1]
#随机打乱
>>> random.shuffle(values)
>>> values
[2, 4, 6, 5, 3, 1]
#随机范围0<=n<=10
>>> random.randint(0,10)
#随机范围0<=n<10 ,step=2
>>>random.randrange(0, 10,2)#相当于 choice(range(start, stop, step))
#随机0-1
>>> random.random()
0.9406677561675867
#随机N位整数
>>> random.getrandbits(200)
335837000776573622800628485064121869519521710558559406913275
伪随机,可用以下方式修改随机seed:
random.seed() # Seed based on system time or os.urandom()
random.seed(12345) # Seed based on integer given
random.seed(b'bytedata') # Seed based on byte data