
public static void main(String[] args) {
BigDecimal number = new BigDecimal(1);
long startTime = System.currentTimeMillis();
for (int i = 1; i < 500000; i++) {
number = number.multiply(new BigDecimal(i));
}
System.out.println("Generating took: " + (System.currentTimeMillis() - startTime) + "ms. Creating String.");
startTime = System.currentTimeMillis();
String result = number.toPlainString();
System.out.println("String generation took: " + (System.currentTimeMillis() - startTime) + "ms");
FileUtils.writeStringToFile(new File("Path/To/File"), result);
}
控制台的输出是:
Generating took: 181324ms. Creating String.
String generation took: 710498ms
这表明了toPlainString()方法花了多长时间.
我知道我们正在处理大量的数字(在上面的例子中是数百万的数字)但我想知道是否有任何方法来加速这种方法,我该怎么做呢?
谢谢!
编辑#1:在帖子中添加的毫秒时间计算的唯一原因是为了将“长”带入预期,并且可能证明代码的行为以防所有读者都无法重现该问题.我想要做的是确定为什么在我的情况下花了这么长时间,最重要的是如何加快转换为String的过程.
在这里,可能需要注意的是,在这种特殊情况下,它实际上不是BigDecimal中的字符串创建,而是BigInteger中的字符串创建.在给定示例中计算的值是大因子,因此实际上是积分值.然后,BigDecimal的内部比例字段将为0,并且查看toPlainString方法会显示在这种情况下,将返回内部intVal字段的字符串值:
public String toPlainString() {
if(scale==0) {
if(intCompact!=INFLATED) {
return Long.toString(intCompact);
} else {
return intVal.toString();
}
}
...
}
这个intVal字段是一个BigInteger,这是这里的实际罪魁祸首.
下面的程序并不是一个合适的“微基准”,而只是假定性能的估计:它创建了几个阶乘,并生成这些的字符串表示:
import java.math.BigDecimal;
public class BigDecimalToPlainStringPerformance
{
public static void main(String[] args)
{
for (int n = 10000; n <= 50000; n += 5000)
{
BigDecimal number = factorial(n);
long before = System.nanoTime();
String result = number.toPlainString();
long after = System.nanoTime();
double ms = (after - before) / 1e6;
System.out.println(n + "! took " + ms +
" ms, length " + result.length());
}
}
private static BigDecimal factorial(int n)
{
BigDecimal number = new BigDecimal(1);
for (int i = 1; i < n; i++)
{
number = number.multiply(new BigDecimal(i));
}
return number;
}
}
使用Java 7(u07),在我的(旧)PC上,输出是沿着的
10000! took 514.98249 ms, length 35656
15000! took 1232.86507 ms, length 56126
20000! took 2364.799995 ms, length 77333
25000! took 3877.565724 ms, length 99090
30000! took 5814.925361 ms, length 121283
35000! took 8231.13608 ms, length 143841
40000! took 11088.823021 ms, length 166709
45000! took 14344.778177 ms, length 189850
50000! took 18155.089823 ms, length 213232
幸运的是,这个性能问题已在Java 8中得到修复.对于Java 8(u45),输出是
10000! took 77.20227 ms, length 35656
15000! took 113.811951 ms, length 56126
20000! took 188.293764 ms, length 77333
25000! took 261.328745 ms, length 99090
30000! took 355.001264 ms, length 121283
35000! took 481.912925 ms, length 143841
40000! took 610.812827 ms, length 166709
45000! took 698.80725 ms, length 189850
50000! took 840.87391 ms, length 213232
表明性能得到了显着改善.
从快速浏览OpenJDK中的提交日志开始,有一个提交可能与此处最相关:
Accelerate conversion to string by means of Schoenhage recursive base conversion
(我没有验证这一点,但它似乎是唯一一个专门致力于提高toString性能的人)
转载注明原文:java – BigDecimal toPlainString需要很长时间才能生成String - 乐贴网