java - 为什么加起来解析的双精度数比在 Java 中使用 BigDecimal 慢?
问题描述
为什么是
result += Double.parseDouble(numberAsString)
result
作为一个原始人,double
比
result = result.add(new BigDecimal(numberAsStrings))
result
作为一个BigDecimal
?
基准:
@Setup
public void beforeEach() {
numbersAsStrings = new String[NUMBER_COUNT];
double currentNumber = 1;
for (int i = 0; i < NUMBER_COUNT; i++) {
numbersAsStrings[i] = String.valueOf(currentNumber);
currentNumber += 0.1;
}
}
@Benchmark
public double addUpDoublesParsedFromString() {
double result = 0;
for (int i = 0; i < numbersAsStrings.length; i++) {
result += Double.parseDouble(numbersAsStrings[i]);
}
return result;
}
@Benchmark
public BigDecimal addUpBigDecimalsFromString() {
BigDecimal result = new BigDecimal(0);
for (int i = 0; i < numbersAsStrings.length; i++) {
result = result.add(new BigDecimal(numbersAsStrings[i]));
}
return result;
}
由于原语通常具有计算速度比非原语更快的声誉,因此结果令人惊讶(至少对我而言):
Benchmark Mode Samples Score Score error Units
t.n.b.n.BigDecimalVsDouble.addUpDoublesParsedFromString thrpt 4 484.070 59.905 ops/s
t.n.b.n.BigDecimalVsDouble.addUpBigDecimalsFromString thrpt 4 1024.567 170.329 ops/s
添加 BigDecimals 的速度为 1024.567 ops/s,但使用原语(在 JMH 中进行基准测试)的添加速度仅为 484.070 ops/s。
为什么会这样?如果有一种方法可以优化double
从字符串解析的原语的添加速度超过BigDecimal
,请在您的答案中包含此内容。
解决方案
你真的在做两件事。解析和添加,但是您指责原始添加速度较慢[如果您真的剖析了最初的问题和您的评论,“由于原语通常比非原语具有计算速度更快的声誉,因此结果令人惊讶(至少对我而言) ):"]。
也许加法运算不是双倍的慢速运算。也许对原语的解析速度较慢,而添加原语则更快。我会尝试更多的基准测试,如下所示
double[] doubleValues;
BigDecimal[] bdValues;
@Setup
public void beforeEach() {
numbersAsStrings = new String[NUMBER_COUNT];
doubleValues = new double[NUMBER_COUNT];
bdValues = new BigDecimal[NUMBER_COUNT];
double currentNumber = 1;
for (int i = 0; i < NUMBER_COUNT; i++) {
numbersAsStrings[i] = String.valueOf(currentNumber);
doubleValues[i] = Double.parseDouble(numbersAsStrings[i]);
bdValues[i] = new BigDecimal(numbersAsStrings[i]);
currentNumber += 0.1;
}
}
//additional benchmarks
@Benchmark
public double addUpDoubles() {
double result = 0;
for (int i = 0; i < numbersAsStrings.length; i++) {
result += doubleValues[i];
}
return result;
}
@Benchmark
public BigDecimal addUpBigDecimals() {
BigDecimal result = new BigDecimal(0);
for (int i = 0; i < numbersAsStrings.length; i++) {
result = result.add(bdValues[i]);
}
return result;
}
@Benchmark
public void doublesParsedFromString() {
for (int i = 0; i < numbersAsStrings.length; i++) {
Double d = Double.parseDouble(numbersAsStrings[i]);
}
}
@Benchmark
public void bigDecimalsParsedFromString() {
for (int i = 0; i < numbersAsStrings.length; i++) {
BigDecimal bd = new BigDecimal(numbersAsStrings[i]);
}
}
//original benchmarks-----------------------
@Benchmark
public double addUpDoublesParsedFromString() {
double result = 0;
for (int i = 0; i < numbersAsStrings.length; i++) {
result += Double.parseDouble(numbersAsStrings[i]);
}
return result;
}
@Benchmark
public BigDecimal addUpBigDecimalsFromString() {
BigDecimal result = new BigDecimal(0);
for (int i = 0; i < numbersAsStrings.length; i++) {
result = result.add(new BigDecimal(numbersAsStrings[i]));
}
return result;
}
还要考虑这样一种可能性,即较短的数字可能会为 BigDecimal 快速解析,而较长的数字可能不会。我会尝试使用不同的数字范围进行基准测试
推荐阅读
- javascript - 无法在反应中设置状态
- javascript - 在 HTML 中创建表单时如何创建链接到其各自选项卡的选项卡按钮
- tensorflow - Tensorflow 转换后推理 Retinanet/Keras 模型
- dataframe - 添加列计数累积的先前重复值
- reactjs - 无法从 React JS 应用程序调用 WSO2 IS 5.9.0 api?
- c# - 如何将包含 --data-urlencode 的 curl 转换为 HttpClient 调用?
- php - PHP如何在特殊字符之前获取字符串?
- git - Git 恢复提交并使用 LFS 文件跟踪:问题
- javascript - 如何从另一个单独的文件的 js 类继承 js 类?
- r - 如何在 R 中启用 SSL 以连接到 Oracle JDBC