decimal 对于浮点数的计算提供了极大的便利性,让我们在使用浮点数进行大小计算的时候不用担心精度丢失的问题,decimal库能处理小数点后 2^31 位数字,对于绝大多数的项目精度要求是足够的,简而言之,decimal 可以解决我们绝大多数的浮点数精度计算场景。
由于golang中默认是没有decimal类型的,所以要解决上述的问题,需要使用第三方库包decimal。
github 地址:https://github.com/shopspring/decimal
1. 介绍
1.1 精度丢失的 case
1 | func TestFloat(t *testing.T) { |
上面的精度就发生了丢失,浮点数的位数虽然我们看到的是 1100.1
,但对于浮点数的计算而言却是无限接近于 1,但与 1 不等。
当我们需要对 float
的数据进行计算的时候,我们可以使用第三方的 decimal 包来解决这个问题。
1.2 Decimal 的应用场景
decimal 的应用场景主要出现在对 float 浮点数进行加减乘除操作的时候,尤其是对于银行金融一块的业务,如果精度丢失,一笔交易上面的损失可以忽略不计,但当交易的规模达到几千万或者亿甚至几十亿的时候,这个时候的损失就会大的吓人了。
Decimal library can “only” represent numbers with a maximum of 2^31 digits after the decimal point.
小数点后 2^31 位数字,对于绝大多数的项目精度要求是足够的,简而言之,decimal 可以解决我们绝大多数的浮点数精度计算场景。
对于上面精度丢失的 case,当我们引入 decimal 包之后,我们可以得到正确的结果。
1 | func TestDecimalOne(t *testing.T){ |
计算结果的精度没有丢失,计算结果正确。
2. 使用
使用 decimal 的时候,切记浮点数计算所有数据的初始化必须通过 decimal 进行,否则还是会导致精度的丢失,为什么这么说呢,看看下面的例子你就明白了。
1 | import ( |
2.1 都要decimal
上面的 case 就是因为 100 没有使用 decimal 进行初始化导致最后计算的精度被扩大了。正确的处理方式如下:
1 | import ( |
2.2 获取结果的整数部分
使用 IntPart
可以获取到浮点数计算结果的整数部分。
1 | func TestDecimalTwo(t *testing.T){ |
2.3 小数点后填充
使用 IntPart
可以对计算后的数据进行小数点位数的补零填充。
1 | func TestDecimalThree(t *testing.T){ |
2.4 比较数字的大小
浮点数的比较 decimal 提供了一些比较有用的函数方法,这里列举了一部分。
1 | import ( |