C语言 如何在Java 17中实现Java 8的数学行为?

s3fp2yjn  于 2023-05-22  发布在  Java
关注(0)|答案(1)|浏览(120)

我们有一个不断增长的代码库,其中还涉及对数据进行数学计算并将其历史存储。现在我们需要继续从Java 8迁移到Java 17,但我们注意到Java 17中的计算结果不同!我们尝试实现相同计算行为的原因是可能的重新计算和历史数据比较(检查结果是否正确计算,新计算是否等于保存的值)。
经过大量的研究,我已经知道,Java 8使用了优化,如使用更多的浮动精度,如果在系统上可用。它们使用内部函数在运行时修改数学运算以提高性能。而且他们依赖于fdlibm 5.3,一个原生的c数学库。在Java 17中,他们将fdlibm从c移植到了java,并至少在StrictMath中使用它,但仍然有一些使用本机代码的内在函数。
我认为实现我所尝试的关键是理解他们如何以及使用哪些选项编译内部函数使用的本机数学代码。
我构建了一个JNI库,它代表了exp、log、sqrt等函数。原生fdlibm我尝试了不同的优化,如-Ofast,但结果仍然不完全相同。
也许像除法、乘法、加减运算符的代码也改变了?
我在同一个系统上运行了测试,所以应该是可比的。

有什么想法可以提取Java 8的数学行为,以便在Java 17中使用它进行遗留计算吗?

使用Math.exp进行不同计算的示例:

JVM VERSION: 1.8.0_362 
--- Input number: 0.003978202863827189 
java.lang.Math.exp       : 1.0039861264165226 

JVM VERSION: 17.0.6
--- Input number: 0.003978202863827189 
java.lang.Math.exp       : 1.0039861264165224

上面输出的示例代码:

public class Exp {

    public static void main(String[] args) {
        System.out.println(System.getProperty("java.library.path"));
        
        double input = Double.valueOf(args[0]);

        System.out.println("JVM VERSION: " + System.getProperty("java.version"));
        System.out.println("---");
        System.out.println("Input number: " + input);
            
        System.out.println("Math result (java.lang.Math.exp):");
        System.out.println(" -> " + Math.exp(input)); 

    }
}
daupos2t

daupos2t1#

当比较浮点数时,你应该始终考虑到所涉及的数字的准确性。该精度几乎总是比浮点表示的精度低得多。因此,数学运算是否变得更精确一点,对你的结果来说并不重要。
因此,在“检查结果是否计算正确”时,应考虑结果的准确性。

相关问题