Java 中的精确混合比较 BigInteger 和 double

Exact mixed comparison BigInteger and double in Java

提问人:Rúben Dias 提问时间:1/24/2023 更新时间:1/25/2023 访问量:55

问:

刚刚注意到 Python 和 JavaScript 有确切的比较。 Python 中的示例:

>>> 2**1023+1 > 8.98846567431158E307
True

>>> 2**1023-1 < 8.98846567431158E307
True

和 JavaScript:

> 2n**1023n+1n > 8.98846567431158E307
true

> 2n**1023n-1n < 8.98846567431158E307
true

任何类似的东西都可用于 Java,除了将两个参数转换为 大十进制?

Java 比较

评论

0赞 Dawood ibn Kareem 1/24/2023
相关新闻: stackoverflow.com/q/17960186
0赞 Dawood ibn Kareem 1/24/2023
现在我已经有几个小时的时间来思考这个问题,我相当确定比较 to 的唯一方法是将它们都转换为 ,或者弄乱钓鱼序列。前者并不像听起来那么糟糕,因为转换为 - 所有将是一个包装器,包括规模和精度等内容。doubleBigIntegerBigDecimalBigIntegerBigDecimalBigDecimalBigInteger
0赞 Dawood ibn Kareem 1/24/2023
好吧,你真的无法绕过这个开销。即使您可以直接转换为进行比较。doubleBigInteger
0赞 Rúben Dias 1/26/2023
另一种解决方案是将 Java 双精度浮点值转换为有理数。但我不知道一些有理数集成到 JDK 中,可能需要第三方库。
1赞 Dawood ibn Kareem 1/28/2023
如果你能找到(或编写)一个有理数库,我会感到非常惊讶,它在比较 a 和 a 时表现更好。您在答案中概述的算法可能会运行良好,但我不认为它与处理有理数有任何关系。BigDecimaldoubleBigInteger

答:

0赞 Rúben Dias 1/25/2023 #1

初步答案,即口头解决方案草图:

我对可以转换的解决方案持怀疑态度 转换为 BigDecimal,因为此转换会导致 基数从 base=2 移动到 base=10。一旦 作为 Java 双精度浮点值的指数 与二进制精度不同,这会导致额外的数字和冗长 pow() 操作,可以通过检查来验证 一些开源的BigDecimal(double) 构造函数实现。

可以通过 Double.doubleToRawLongBits(d) 获取尾数。 如果 Java 双精度浮点值不是次正态值 所有需要做的是(原始和DOUBLE_SNIF_MASK)+ (DOUBLE_SNIF_MASK+1) 其中 0x000fffffffffL 这意味着 整数 Java 原语类型 long 应该足以 携带尾数。现在的挑战是进行比较 还要考虑浮点数的指数。

但我必须承认,我还没有时间工作 出一些 Java 代码。我也想到了一些 使用另一个的 bigLength() 进行优化 参数,在此设置中为 BigInteger。 使用 bitLength() 将加快比较速度。 一个简单的启发式方法可以实现一个快速路径,这样 尾数可以忽略不计。已经是指数 的 double 和 BigInteger 的 bitLength() 为比较结果提供足够的信息。

只要我有时间并运行原型,我可能会 在此处发布一些 Java 代码片段。但也许有人 已经面对问题了。我的一般假设是,快速或 即使是超快速的例程也是可能的。但我没有 很多时间在互联网上搜索并找到一个 实现,这就是为什么我把问题推迟到 堆栈溢出,也许其他人也有同样的情况 问题和/或可能指向一个完整的解决方案?