如果有一天,有人告诉你三个 0.1 加起来不等于 0.3 你会不会觉得很惊讶?但事实如此:
1 | 0.1 + 0.1 + 0.1 == 0.3 |
这是为什么呢?这就涉及到了浮点运算的精度问题。
Why
计算机一般以二进制存储数据。在十进制里,0.1 是个精确值,但在二进制里,0.1 是一个无限循环小数:
1 | a = 0.1 |
1 | 0.00011001100110011001100110011001100110011001100110 |
所以从存入的那一刻,其数值就已经从精确值变为了不定值。
在某些需要精确计算的场合,这非常致命。
How
如何解决?
其一是使用 decimal 模块,这里也仅介绍 decimal 模块,在我看来,它几乎满足所有要求。
decimal
Decimal is based on a floating-point model which was designed with people in mind.
它模仿人类十进制计算方法进行计算:
- 绝对精确:0.1 + 0.1 + 0.1 = 0.3
- 有效位保留:0.30 * 0.200 = 0.06000
- 四舍五入
Decimal
1 | class decimal.Decimal(value="0", context=None) |
value
可以是整数、字符串、浮点数等。
1 | 1) # 一般用于表示大数字 Decimal( |
context
context 翻译为上下文对象,详见 wiki。
getContext()
1 | # 设置运算精度 |
目前来说一般用于算法题中……有的需要进行大数字计算,或者是高精度比较相等之类的,就可以用到 decimal。