AS400/RPG 中的舍入与 Java 中的舍入

Rounding in AS400/RPG vs Rounding in Java

我正在尝试将一些 AS400/RPG 代码转换为 Java

我能够在网上找到 example 反映了我在代码中看到的内容:

d elevensix       s             11  6 inz(26285.88991)  
d seventwo        s              7  2                   
c                   eval(h)   seventwo      = elevensix 
c                   eval      *inlr = *on

我在 Java 中编写了代码,我发现我在 RPG 代码中看到的舍入结果与我在 [=16] 中看到的舍入类型不匹配=].这是我在 Java:

中进行的舍入示例
private Long roundAmount(Double amount) {
        return Math.round(amount);
}

在实践中,我的代码生成的结果与 RPG 代码的结果相匹配,但是我发现在逻辑上不一致的示例;有些像预期的那样四舍五入,有些则没有。

我曾与 Java 一起工作过;这是我第一次涉足 RPG。老实说,我什至不知道从哪里开始。例如上面的RPG代码;它究竟是如何工作的?我看到操作的结果被放入一个标有 2 位小数的变量中;舍入是隐式的吗?我 find the following definition 在线搜索 Java 如何处理舍入:

The Math.round() method in Java is used to round a number to its​ closest integer. This is done by adding 1/2 to the number, taking the floor of the result, and casting the result to an integer data type.

老实说,这很简洁明了。我还没有在 RPG 中找到关于它如何工作的类似解释;需要明确的是,这是在使用 RPG 的 AS400 上编程,但比我认为当前标准的版本要旧得多。然而,即使是对现代实施的解释也将是一个开始。

您发布的 RPG 代码与您的 Java 代码不同。

Java 代码将 Double 转换为 Long,而 RPG 代码将 6 位小数舍入为 2 位小数。

其中,elevensix是一个11位数字,其中6位小数部分,5位整数部分; seventwo是一个7位数字,其中2位小数部分,5位整数部分。

eval(h)elevensix 的值复制到 seventwo 并使用“half-adjust”逻辑将其四舍五入为 2 个十进制数字(这就是“h”的含义因为,没有它,小数点将被截断)。

来自RPG documentation (that you can find also in PDF format) and in particular here

Half-adjusting is done by adding 5 (-5 if the field is negative) one position to the right of the last specified decimal position in the result field.

这对我来说似乎类似于 Math.round 所做的,但概括为任何小数位。 它也对应于 Java Math RoundingMode.HALF_UP.

由于您没有提供一些产生不一致的实际示例,因此很难为您提供明确的解决方案。

无论如何,Java 中的 RPG 代码可以使用 BigDecimals 的方法 setScale 复制,如下所示:

double result = new BigDecimal(amount.toString())
        .setScale(2, RoundingMode.HALF_UP)
        .doubleValue();

您也可以考虑使用 Apache Commons Math 方法 round,从实现的角度来看,它的作用几乎相同。

您的问题也可能是由 Double 的精度有限引起的,在这种情况下,您应该只使用 BigDecimals,请参阅 Double vs. BigDecimal?