如果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是答案,那肯定是一个奇怪的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文笔超惊艳的高质量现言小说(超好看的三本
- 下一篇: 从JPA到Hibernate的旧版和增强