python教程python简单教程

Python中,数,用各种形式表示,不同形式的数有各自的用途。

整数
整数,令人惊叹于它的简单。两个整数相除,例如4/3,得到一个浮点数,并且(4/3)*3的结果也是浮点数4.0。即便你没有定义浮点数,在进行除法运算的时候,它会自动出现。

浮点数
浮点数不是一般意义的数。按照数学上的规定,数应该遵循如下原则:减法是加法的逆运算,加法结合律,等等。

例如:

1 + 2 - 2 - 1
0

0.1 + 0.2 - 0.2 - 0.1
2.7755575615628914e-17
两个数相加,再分别减去它们,上述居然出现了不同的结果。
它们也不会遵循结合律:a + (b + c) = (a + b) + c

a = 2**-53
(a + a) + 1 == a + (a + 1)
False
以上仅仅是浮点数运算中存在的两个“小问题”,还不令你惊讶吗?此处不便将浮点数各种出乎意料的运算一一展现。

分数
很多看似简单的程序,遇到分数,就会出问题,比如运算时间暴增,算法的复杂度加倍。遇到分数的时候,算法时间不是跟输入成正比,而是指数增长。

如果时间足够长,内存爆掉也是常见的。

加法就是其中一个典型例子

print(set(type§ for p in primes))
one = fractions.Fraction(1)
before = datetime.now()
res = sum(one/p for p in primes[:10000])
after = datetime.now()
print(“It took”, after-before)
print(“Size of output”, len(str(res)))
print(“Approximate value”, float(res))
{}
It took 0:01:16.033260
Size of output 90676
Approximate value 2.7092582487972945
这段程序,计算了一些素数的倒数的和。在笔记本电脑上,10000个这样的数相加,要1分钟,最终输出结果的大小超过了90K。

对比着,执行浮点数运算,性能更好。

print(set(type§ for p in primes))
before = datetime.now()
res = sum(1/p for p in primes[:10000])
after = datetime.now()
print(“It took”, after-before)
print(“Size of output”, len(str(res)))
print(“Approximate value”, float(res))
{}
It took 0:00:00.000480
Size of output 17
Approximate value 2.709258248797317
这次运行时间小于1毫秒,并且,者还可能是因为用datetime测量产生的误差,快了10000倍。而且输出结果的大小仅有17比特,下降了1000多倍。然而,计算结果有误差。

Approximate value 2.7092582487972945
Approximate value 2.709258248797317
1234567891234
误差低于 10的-14次方,这就如同将火箭发射月球上偏差了1毫米,用浮点数计算得到的结果足够精确,并且效率更高。

对此,一般的观点是:Python进行分数运算很慢。对此,Python可以承担10倍的责任,但不是10000倍。有一个第三方模块,quicktions,用Cython执行分数的运算。

用quicktions,真的“很快”。在我的笔记本电脑上,上面那个程序的时间,从1分16秒,缩短到1分15秒。

问题在于程序本身,在程序中,我精心选择了一种输入方案,以素数作为分母进行分数相加,这本来就是一种很坏的情况。

自学python,可以找我领取参考教程。我的抠抠前面是169,中间是0729,后面是198,数字连起来就行了

小数
小数在财务中用途最广,最无聊的是居然以法律的方式规定了小数的形式。然而,Python中所有的小数点运算,都有上下文精确度问题,对此,可以用专门的模块解决。

getcontext().prec = 6
Decimal(1) / Decimal(7)
Decimal(‘0.142857’)

getcontext().prec = 28
Decimal(1) / Decimal(7)
Decimal(‘0.1428571428571428571428571429’)
在实际项目中,代码中设置精度的位置和进行计算的位置可能间隔几百行,计算可以在一个函数中,也可以在另外一个文件。

最安全的方法是使用localcontext:

getcontext().prec = 6

6853 lines elided

… with localcontext() as ctx:
… ctx.prec = 10
… Decimal(1) / Decimal(7)

Decimal(‘0.1428571429’)
只要你认真地用localcontext,小数运算不会出问题。

总结
你在程序中用到数字的时候,是否想过:应该用什么类型?会发生什么?误差重要吗?

什么也不想,会意味着暗藏bug。

你可能感兴趣的:(python教程python简单教程)