java - Java 8 和 Java 13 中的 Math.pow() 返回不同的结果
问题描述
以下代码在 Java 8 和 Java 11 上返回不同的结果。
class Playground {
public static void main(String[ ] args) {
long x = 29218;
long q = 4761432;
double ret = Math.pow(1.0 + (double) x / q, 0.0005);
System.out.println("val = " + String.format("%.24f", ret));
}
}
爪哇 8:
val = 1.000003058823805400000000
Java 11:(与 Python、Rust 的结果相同)
val = 1.000003058823805100000000
这些问题是:
- 有任何文件来描述这种行为吗?
- 如何
Math.pow()
在 Python 中实现 Java 8? - 如何使用 Java 8 库确保与旧程序的严格一致性?
解决方案
如果我们只使用 Double.toString() 打印答案,那么两个不同的结果将是
1.0000030588238054
1.0000030588238051
末尾的额外数字只是 String.format() 的一个因素。我们看到这些数字仅在最后一个有效的十进制数字上有所不同。将这两个数字转换为十六进制给出
1.000033518c576
1.000033518c575
所以二进制表示在最后一位(ulp)仅相差一个单位。
阅读Math.pow的规范,我们发现
“计算结果必须在精确结果的 1 ulp 范围内。”
真实值接近 1.000003058823805246468 ( WolframAlpha ) 介于两个答案之间,因此两者都在规范范围内。
所发生的一切是该库在算法上略有改变,也许是为了让它更快。
推荐阅读
- python - 如何使用 django rest 框架获取 csv 文件和 excel 格式(xls xlsx,..)
- vector - 如何方便地将二维数组转换为二维向量?
- java - 对象的堆与字符串常量池内存表示
- javascript - ThreeJS ExtrudeGeometry HOLE 从点
- angular - 如何检查组件输入值是否已更改或未更改
- ruby-on-rails - Capistrano 3 错误 - extconf.rb:29:in `
':“libxml2”包不可用。(运行时错误) - kubernetes - Kubernetes:无法获取 GCE GCECloudProvider 并出现错误
- python-3.x - 使用 Python 从 AWS S3 下载文件
- swift - 在另一个字典上使用字典的键崩溃
- node.js - 使本地主机端口可通过互联网访问 - NodeJS