java - 在 Java 中,哪种阶乘函数的实现通常更快?
问题描述
我正在考虑阶乘函数的两种可能实现。我不确定哪一个通常更快。我可以想到为什么两者都可能更快的论点。(我实际上并没有尝试实现快速阶乘函数;我只是对此感到好奇。)
方法一:
public static BigInteger factorial (int n) {
BigInteger product = new BigInteger("1");
for (int i = 1; i<=n; i++) {
product = product.multiply(BigInteger.valueOf(i));
}
return product;
}
方法二:
public static BigInteger factorial (int n) {
BigInteger product = new BigInteger("1");
for (int i = n; i>=1; i--) {
product = product.multiply(BigInteger.valueOf(i));
}
return product;
}
本质上,方法 1 执行乘法 1*2*...*n,为 (( 1 * 2 )* 3)*...,方法 2 计算相同项的乘积,但顺序相反:( ( n * (n-1) ) * (n-2) )*...
我的问题是:其中哪些通常具有更快的运行时间?
我知道乘以更大的数字会更慢,但是当将许多项相乘时,尽可能长时间地保持乘积的值相对较小(方法 1)或者在执行最大项的乘法时是否更快总产品仍然更小(方法2)?
是否取决于大小n
?如果我使用long
或int
代替BigInteger
(除非溢出),或者如果我使用另一种语言,答案会有所不同吗?
解决方案
我通过JMH运行了两种不同的方法,这就是你应该如何对 java 代码进行基准测试,因为它负责减轻热点预热等的影响:
n = 100
platform: JDK11, intel x86-64 2,9Ghz core i5 laptop.
Benchmark Mode Cnt Score Error Units
MyBenchmark.highToLow thrpt 25 175954,070 ± 20689,017 ops/s
MyBenchmark.lowToHigh thrpt 25 184311,758 ± 18965,592 ops/s
看起来从低到高的胜利,但事实并非如此 - 这是相同的数字,这是统计噪音。
使用更大的 n,并减少迭代和运行时间可以让您快速获得答案:
n = 10000
platform: JDK11, intel x86-64 2,9Ghz core i5 laptop.
Benchmark Mode Cnt Score Error Units
MyBenchmark.highToLow thrpt 6 34,683 ± 7,075 ops/s
MyBenchmark.lowToHigh thrpt 6 31,230 ± 21,437 ops/s
这归结为相同;这并不重要。
换句话说,同样快。
推荐阅读
- reactjs - React hooks 随时更新
- python-3.x - 如何检测文件格式的编码
- javascript - 下载为 JPG、PNG 时,Signature Pad 上的 Canvas Signature 变为全黑
- r - 如何分割热图或绘制具有特定范围的边界?
- python - jupyter notebook InternalError: cudaGetDevice() 失败。状态:CUDA 驱动程序版本对于 CUDA 运行时版本不足
- ruby-on-rails - 视图上的 Rails 模型验证错误无法正确呈现
- spring-boot - 为什么 intellij 运行 SpringBootApplication 很好,而打包的 jar 找不到资源?
- spring-boot - Springboot Web 安全配置未重定向到登录页面
- javascript - 检测文档何时完全加载(包括图像)
- python - 你如何在python中表示这个字符?