1事情始末
最近和媳妇回去买房,一切都很愉快,最后竟然被一个房管局的系统给“算计”了,作为程序员的我,当时就不淡定了,****!这么重要的事情,重要的时刻,竟然出现这么严重的Bug!
事情是这样的。
交完首付款,签完字之后,签约中心的财务负责人,很负责任的让我们核对系统上的信息,
个人信息正确...
联系方式正确...
.....
首付款正确...
不对啊,
我定睛一看,这不对啊!首付款和商贷占比不等于100%,都是系统自动结算,首付款30.19%,商贷69.82%,这是哪个程序员干的事?
财务小姐姐说没事,可能是系统不稳定,一会换台电脑操作就可以了,叫我们切莫惊慌失措。可以先回去,他会处理的。
作为程序员的我,当时就不淡定了,也只能故作镇定,你们系统难道是本地部署啊,换台电脑就解决了。这很明显就是一个Bug!精度不够!一个初级程序员才会犯的错。
怎么可能手动修改啊,用大腿想想也知道,手动修改占比,金额不就又变了嘛。最终,多交了首付款,把占比的问题给“凑”成了100%,也算“解决”了系统Bug,不然无法提交信息到房管局审核,耽误的还是自己的时间。开发者的锅,我替他背了。
基于此,今天就简单聊下Java中关于金额的处理的事儿。
2
java对金额处理
众所周知,程序在处理货币金额类数据时,最关键的是保持精度,丢失精度就丢失了准确性,这是不可接受的,银行存蓄,股票,基金都是如此。java处理金额,一定不能用double和float类型,二进制无法准确表达十分之一,就像十进制无法准确表达三分之一一样。处理金额要使用Bigdemical类。
API
构造器 | 描述 |
---|---|
BigDecimal(int) | 创建一个具有参数所指定整数值的对象 |
BigDecimal(double) | 创建一个具有参数所指定双精度值的对象 |
BigDecimal(long) | 创建一个具有参数所指定长整数值的对象 |
BigDecimal(String) | 创建一个具有参数所指定以字符串表示的数值的对象 |
方法 | 描述 |
---|---|
add(BigDecimal) | BigDecimal对象中的值相加,然后返回这个对象 |
subtract(BigDecimal) | BigDecimal对象中的值相减,然后返回这个对象 |
multiply(BigDecimal) | BigDecimal对象中的值相乘,然后返回这个对象 |
divide(BigDecimal) | BigDecimal对象中的值相除,然后返回这个对象 |
toString() | 将BigDecimal对象的数值转换成字符串 |
doubleValue() | 将BigDecimal对象中的值以双精度数返回 |
floatValue() | 将BigDecimal对象中的值以单精度数返回 |
longValue() | 将BigDecimal对象中的值以长整数返回 |
intValue() | 将BigDecimal对象中的值以整数返回 |
更详细了解:https://zhuanlan.zhihu.com/p/110540854
同时,如果想要更优雅的处理金额和货币信息,这里推荐一个金额处理的工具类 Joda-Money。欢迎关注我们,公号终码一生。
Joda-Money 是一个用于表示货币金额的开源Java类库,使用该类库处理金额相关数据,可以让你免去对数据精度的担忧。
只需要引入相关依赖,在 pom.xml 中添加如下内容:
<dependency>
<groupId>org.joda</groupId>
<artifactId>joda-money</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>6.0.1.GA</version>
</dependency>
Joda-Money 提供了一个 Money 来表述一个货币金额 (底层使用的是 BigDecimal ),该类提供了一系列静态方法创建相应的对象,注意,在创建 Money 对象时,必须指定货币代码来标注该数据对应的具体币种!比如人民币的货币代码是CNY, 美元的货币代码是 USD ,日元的 JPY 等。这里不对方法使用做过多介绍,需要直接查文档。
文档 | https://www.joda.org/joda-money/index.html |
---|---|
Github | https://github.com/JodaOrg/joda-money |
3数据库中金额存储类型
那么存储时需要注意些什么呢?
以 MySQL 为例。
在数据库中,金额的存储我们常用Decimal和Numric类型表示,很少使用float或者是double,还是因为这两者是以二进制储存的,存在一定的误差。此外还要注意的就是默认值,一定写成0.00,不要用默认的NULL,否则在进行加减乘除等操作时,会带来一些不必要的麻烦。当然,加减乘除的操作,我们在java中也是要使用Bigdemical类封装好的函数,而非直接使用运算符。
参考:https://blog.csdn.net/xzp_12345/article/details/79460410
4最后
金额处理不可小视,本文只是简单的介绍了下,并推荐相关的工具类,并没有去做深入的研究,感兴趣的小伙伴,可以做更深入的研究。好了,上面的内容希望对大家在开发中有所帮助。
—END—