前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java算术运算性能设计要点

Java算术运算性能设计要点

作者头像
物流IT圈
发布2019-11-18 22:21:23
7030
发布2019-11-18 22:21:23
举报
文章被收录于专栏:物流IT圈物流IT圈

如果想进行快速安全的金融财务有关的算术计算,也就是浮点的加减乘除算术运算,请遵循下列条件:

首先,不要使用float进行任何算术运算,因为它的精度太低只有32位。double也不是很精确,看下面案例:

代码语言:javascript
复制
System.out.println( "362.2 - 362.6 = " + ( 362.2 - 362.6 ) );

结果是"362.2 - 362.6 = -0.4000000000000341"

当使用double避免与非整数值一起工作,使用long进行加减算法,进行除法和乘法请使用Math.round/rint/ceil/floor。

再看看double和BigDecimal比较,让我们用1.5% 乘362.2$ 计算,运行100M次:

BigDecima:

代码语言:javascript
复制
int res = 0;final BigDecimal orig = new BigDecimal( "362.2" );final BigDecimal mult = new BigDecimal( "0.015" ); //1.5%for ( int i = 0; i < ITERS; ++i ){    final BigDecimal result = orig.multiply( mult, MathContext.DECIMAL64 );    if ( result != null ) res++;}double:final double orig = 36220; //362.2 in centsfinal double mult = 0.015; //1.5%for ( int i = 0; i < ITERS; ++i ){    final long result = Math.round( orig * mult );    if ( result != 543 ) res++;    //543.3 cents actually}

测试下来,BigDecimal使用了4.899秒,而double使用了0.58秒。如果你的计算正好是52位(double的精确度),尽量使用double,而不是BigDecimal.

如果你仍然想使用BigDecimal作为您的货币计算(很方便,至少!),下面的文字会给你正确的使用BigDecimal的一些提示。

对于BigDecimals您可以同时指定舍入模式和精度,但有一个更方便的方法 - 您可以使用MathContext代替,其中包含精度和舍入的信息。更重要的是,也有一些预定义的,这可以让你模拟float/double/decimal_128算术运算,没有任何四舍五入问题:MathContext.DECIMAL32/DECIMAL64/DECIMAL128。

MathContext.UNLIMITED是一个缺省的MathContext值。但是不要使用它,它等同于一点没有上下文。

你可以使用MathContext进行加减运算,但是对于乘除最好规定一个DECIMAL*上下文,它们是必需的,因为当运算结果有一个无限长的十进制扩展,这些操作需要指定精度。否则会报ArithmeticException错误。

下面是运算同样算术的性能比较:

代码语言:javascript
复制
double0.018秒no MathContext4.1秒MathContext.UNLIMITED3.9秒MathContext.DECIMAL324.2秒MathContext.DECIMAL649.5秒MathContext.DECIMAL12813.9秒

最后,如果你想将一个浮点数转为字符串,好像很容易,实际相当困难,你需要知道的浮点数的二进制表示形式(IEEE-754)。详情将在sun.misc.floatingdecimal类的源代码看看(一般不存在JDK中,因此谷歌搜索它:)),特别是,一个很短的时差法,做了所有的魔术。自从1996年以后没有人敢碰它:)

下面是性能比较:

代码语言:javascript
复制
Double.toString(double)4.1 secBigDecimal.toPlainString12.4 secBigDecimal.toEngineeringString 12.5 sec

请注意:对于double, 请不要将double转为BigDecimal,先将double转为String,再将String转为BigDecimal。

如果你的算术需要将一个字符串作为输入,将其直接转换为BigDecimal。好处是你会避免任何的舍入误差。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 驼马精英 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档