欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

如果BigDecimal是答案,那肯定是一个奇怪的问题

发布时间:2023/12/3 51 豆豆
生活随笔 收集整理的这篇文章主要介绍了 如果BigDecimal是答案,那肯定是一个奇怪的问题 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

总览

许多开发人员已确定BigDecimal是处理金钱的唯一方法。 通常,他们通过用BigDecimal替换double来确定错误或十个错误。 我对此没有说服力的是,也许他们可以解决double处理中的错误以及使用BigDecimal的额外开销。

根据我的比较,当被问到改善财务应用程序的性能时,我知道有时会删除BigDecimal(如果有的话)。 (通常不是造成延迟的最大原因,但是当我们修复系统时,它会升级为最严重的违规者)。

BigDecimal不能改善

BigDecimal有很多问题,因此请选择,但丑陋的语法也许是最糟糕的罪过。

  • BigDecimal语法是不自然的。
  • BigDecimal使用更多内存
  • BigDecimal创建垃圾
  • 对于大多数操作,BigDecimal的速度要慢得多(有例外)

以下JMH基准测试演示了BigDecimal的两个问题:清晰度和性能。

核心代码取两个值的平均值。

双重实现看起来像这样。 注意:需要使用四舍五入。

mp[i] = round6((ap[i] + bp[i]) / 2);

使用BigDecimal进行的相同操作不仅很长,而且还有很多样板代码需要导航

mp2[i] = ap2[i].add(bp2[i]).divide(BigDecimal.valueOf(2), 6, BigDecimal.ROUND_HALF_UP);

这会给您带来不同的结果吗? double的精度为15位,而数字远少于15位。 如果这些价格有17位数字,这将起作用,但对必须理解价格的穷人也不会起作用(即,它们永远不会变得难以置信的长)。

性能

如果您必须承担编码开销,通常这样做是出于性能方面的考虑,但这在这里没有意义。

基准测试 模式 样品 得分了 得分错误 单位
osMyBenchmark.bigDecimalMidPrice thrpt 20 23638.568 590.094 运算/秒
osMyBenchmark.doubleMidPrice thrpt 20 123208.083 2109.738 运算/秒

结论

如果您不知道如何使用双精度整数,或者您的项目要求使用BigDecimal,请使用BigDecimal。 但是,如果您有选择的话,不要仅仅认为BigDecimal是正确的选择。

编码

import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder;import java.math.BigDecimal; import java.util.Random;@State(Scope.Thread) public class MyBenchmark {static final int SIZE = 1024;final double[] ap = new double[SIZE];final double[] bp = new double[SIZE];final double[] mp = new double[SIZE];final BigDecimal[] ap2 = new BigDecimal[SIZE];final BigDecimal[] bp2 = new BigDecimal[SIZE];final BigDecimal[] mp2 = new BigDecimal[SIZE];public MyBenchmark() {Random rand = new Random(1);for (int i = 0; i < SIZE; i++) {int x = rand.nextInt(200000), y = rand.nextInt(10000);ap2[i] = BigDecimal.valueOf(ap[i] = x / 1e5);bp2[i] = BigDecimal.valueOf(bp[i] = (x + y) / 1e5);}doubleMidPrice();bigDecimalMidPrice();for (int i = 0; i < SIZE; i++) {if (mp[i] != mp2[i].doubleValue())throw new AssertionError(mp[i] + " " + mp2[i]);}}@Benchmarkpublic void doubleMidPrice() {for (int i = 0; i < SIZE; i++)mp[i] = round6((ap[i] + bp[i]) / 2);}static double round6(double x) {final double factor = 1e6;return (long) (x * factor + 0.5) / factor;}@Benchmarkpublic void bigDecimalMidPrice() {for (int i = 0; i < SIZE; i++)mp2[i] = ap2[i].add(bp2[i]).divide(BigDecimal.valueOf(2), 6, BigDecimal.ROUND_HALF_UP);}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(".*" + MyBenchmark.class.getSimpleName() + ".*").forks(1).build();new Runner(opt).run();} }

翻译自: https://www.javacodegeeks.com/2014/07/if-bigdecimal-is-the-answer-it-must-have-been-a-strange-question.html

总结

以上是生活随笔为你收集整理的如果BigDecimal是答案,那肯定是一个奇怪的问题的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。