一致的评估和匹配分数值

Consistent evaluation and match the fractional values

我有一个 Web 应用程序,搜索由 ElasticSearch 提供支持。

我使用 ScriptEngine 计算 Java 中的小数值:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
System.out.println("12*0.0254 = " + engine.eval("12*0.0254"));//0.30479999999999996
System.out.println("12000*0.0000254 = " + engine.eval("12000*0.0000254"));//0.3048

如评论中的 SOP 输出所示,对于相同的输入,输出的四舍五入方式不同。

在 UI 中,我使用 JavaScript 的内置 eval() 函数,它与不一致的 Java 输出不匹配。

Java 中获得一致且正确的表达式结果的方法是什么,即 12 * 0.0254 应该始终评估为 0.3048 而不是 0.30479999999999996

仅仅因为两个表达式在数学上是等价的,并不意味着它们在给定的机器算法中计算出相同的值。

The Java Virtual Machine incorporates a subset of the floating-point arithmetic specified in IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std. 754-1985, New York).

2.8.1. Java Virtual Machine Floating-Point Arithmetic and IEEE 754

The key differences between the floating-point arithmetic supported by the > Java Virtual Machine and the IEEE 754 standard are:

The floating-point operations of the Java Virtual Machine do not throw >exceptions, trap, or otherwise signal the IEEE 754 exceptional conditions of >invalid operation, division by zero, overflow, underflow, or inexact. The >Java Virtual Machine has no signaling NaN value.

The Java Virtual Machine does not support IEEE 754 signaling floating->point comparisons.

The rounding operations of the Java Virtual Machine always use IEEE 754 >round to nearest mode. Inexact results are rounded to the nearest >representable value, with ties going to the value with a zero least-significant bit. This is the IEEE 754 default mode. But Java Virtual Machine >instructions that convert values of floating-point types to values of > integral types round toward zero. The Java Virtual Machine does not give any means to change the floating-point rounding mode.

The Java Virtual Machine does not support either the IEEE 754 single extended or double extended format, except insofar as the double and double-extended-exponent value sets may be said to support the single extended format. The float-extended-exponent and double-extended-exponent value sets, which may optionally be supported, do not correspond to the values of the IEEE 754 extended formats: the IEEE 754 extended formats require extended precision as well as extended exponent range.

来源:https://docs.oracle.com/javase/specs/jvms/se10/html/jvms-2.html#jvms-2.8.1.

在 JavaScript 中,我得到了与您相同的结果(https://jsfiddle.net/,Firefox Developer Edition 97.0b5(64 位):

console.log(12*0.0254);
console.log(12000*0.0000254);
0.30479999999999996
0.3048

也许您的 GUI 框架应用了舍入?

您可以将输出格式化为 Java 中的特定小数位数,如下所示:

DecimalFormat df = new DecimalFormat("#.#####");
System.out.println(df.format(12*0.0254));
System.out.println(df.format(12000*0.0000254));