金融应用如何解决金额精度问题(以Quorum、golang为例)

金额精度问题

背景:本文以企业级区块链应用Quorum为例子(该应用由golang编写),说明了如何解决金额精度的问题。

金额精度问题是每一位金融系统开发者要面临的问题,从笔者入行开始,从银行系统,互联网支付公司系统,一直到区块链金融应用,这个问题无处不在。针对此典型问题典型解法如下。

具体例子

工行账户黄金应用(真实存在的应用)的金额单位定义成float64,会在实际中造成什么问题?effective java有提到这个问题的,会造成如下严重后果(我用golang改写如下):


package main

import "fmt"

const TEN_CENTS float64 = 0.1

func main() {

	var itemBought int = 0

	var myfund float64 = 1.00

	for price := TEN_CENTS; price < myfund; price += TEN_CENTS {

		itemBought++

		myfund -= price

		fmt.Println("loop")

	}

	fmt.Println("买到的东西:", itemBought, " 剩余的金额:", myfund)

}

如果用**“go run”**命令运行这个文件会有如下提示输出


vincent@zheng450:~/gopath$ go run currency.go 

loop

loop

loop

买到的东西: 3  剩余的金额: 0.3999999999999999

为什么?就是float64其实不适合用来表示货币

这个问题笔者在同系列博客的《金融应用资金处理安全十问》有阐述,见其中第6点


那么Quorum怎么解决问题?

首先,货币的表示上人家用的是国际标准

考虑到国家间的不同情况,货币形式有不同,会在xml中定义


<currencies>
    <currency type="USD">
        <displayName>Dollar</displayName>
        <symbol>$</symbol>
    </currency>
    <currency type ="JPY">
        <displayName>Yen</displayName>
        <symbol>¥</symbol>
    </currency>
    <currency type="PTE">
        <displayName>Escudo</displayName>
        <symbol>$</symbol>
    </currency>
</currencies>
其次,聪明的做法是绕开这个问题,像比特币,直接没有小数点,以Wei为单位,而其不可以再细分。

见如下代码(core/types/transaction.go)


Amount       *big.Int        `json:"value"

所以都会引入math.big包,没有小数点

人民币怎么办?

定义好形式,比如最小是分,所有的操作统一换成是分,然后计算

过程类似如下:

转换 – 》 计算 – 》 转换


货币精度问题在之前的区块链应用中的解决

  • 比特币 采用超大精度,38位,另外像以太坊之类,都是取math.bigInt,wei是最小不可细分

  • Fabric是搭建底层的channel,证书之类,没有涉及到金额,把这个问题抛给了应用层

银行应用对金额处理的路线之争:

  • 国际贸易结算应用:设置专门的金额类,有符号,有小数,有复杂计算规则

  • 主机核心系统应用:仅和人民币打交道,所以都规定到分,简单化规则

将来我们的应用系统,建议还是走第一套方案,初始就支持国际化,至于增加了计算量,其实主要性能瓶颈不在这里

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值