我正在尝试将一些AS400
/RPG
代码转换为Java
。
我能够在网上找到一个镜像我在代码中看到的示例:
d elevensix s 11 6 inz(26285.88991)
d seventwo s 7 2
c eval(h) seventwo = elevensix
c eval *inlr = *on
我用Java
编写了代码,我发现我在RPG
代码中看到的舍入结果与我在Java
中看到的舍入类型不匹配。以下是我在Java
中所做的四舍五入的示例:
private Long roundAmount(Double amount) {
return Math.round(amount);
}
在实践中,我的代码生成的结果与RPG
代码的结果相匹配,但是我发现逻辑不一致的示例; 有些按预期舍入,有些则不然。
我用Java做过大量工作;这是我第一次涉足RPG
。老实说,我什至不确定从哪里开始。例如,在上面的RPG
代码中;它究竟是如何工作的?我看到操作的结果被放入一个标有 2 位小数的变量中;舍入是隐式的吗?在线搜索时,我发现 Java 如何处理舍入的以下定义:
Java 中的 Math.round() 方法用于将数字四舍五入为其 最接近的整数。这是通过在数字上加 1/2 来完成的, 获取结果的发言权,并将结果转换为整数 数据类型。
老实说,这是清晰简洁的。我还没有找到关于它在RPG
中如何工作的类似解释;需要明确的是,这是在使用RPG
的AS400上进行编程,但比我认为的当前标准要旧得多。然而,即使是对现代实现的解释也将是一个开始。
你发布的RPG代码与你的Java代码不同。
Java代码将Double
转换为Long
,而RPG代码是将小数点后6位的数字四舍五入为小数点后2位的数字。
特别是,elevensix
是一个有 11 位数字的数字,其中 6 位用于小数部分,5 位用于整数部分;seventwo
是一个有 7 位数字的数字,其中 2 位用于小数部分,5 位用于整数部分。
eval(h)
将elevensix
的值复制到seventwo
,并使用"半调整"逻辑将其四舍五入为 2 位十进制数字(这就是"h"代表的,没有它,小数将被截断)。
从 RPG 文档(您也可以找到 PDF 格式)中,特别是在这里:
半调整是通过添加 5(如果字段为负值,则为 -5)1 来完成的 位置位于 结果字段。
在我看来,这似乎与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?。