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

huangapple go评论59阅读模式
英文:

Rounding in AS400/RPG vs Rounding in Java

问题

I'm trying to convert some AS400/RPG code into Java.

I was able to find an example online that mirrored what I am seeing in the code:

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

I have written code in Java and I am finding that the results of the rounding I see in the RPG code, it is not matching the type of rounding I see in Java. Here is a sample of the rounding I am doing in Java:

private Long roundAmount(Double amount) {
    return Math.round(amount);
}

In practice my code generates results that match up to the results from the RPG code however I am finding examples which are inconsistent in the logic; some which round up as expected and others that don't.

I have worked heavily with Java; this is my first foray into RPG. I'm honestly not even sure where to begin. For example, in the RPG code above; how exactly is it working? I see the results of the operation being put into a variable marked with 2 decimal places; is the rounding implicit? Searching online I find the following definition for how Java handles rounding:

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.

Honestly this is clear and concise. I have not found a comparable explanation for how it works in RPG; to be clear this is programming on an AS400 which uses RPG, but a much older version than what I believe the current standard is. However an explanation even for the modern implementation would be a start.

英文:

I'm trying to convert some AS400/RPG code into Java.

I was able to find an example online that mirrored what I am seeing in the code:

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

I have written code in Java and I am finding that the results of the rounding I see in the RPG code, it is not matching the type of rounding I see in Java. Here is a sample of the rounding I am doing in Java:

private Long roundAmount(Double amount) {
		return Math.round(amount);
}

In practice my code generates results that match up to the results from the RPG code however I am finding examples which are inconsistent in the logic; some which round up as expected and others that don't.

I have worked heavily with Java; this is my first foray into RPG. I'm honestly not even sure where to begin. For example, in the RPG code above; how exactly is it working? I see the results of the operation being put into a variable marked with 2 decimal places; is the rounding implicit? Searching online I find the following definition for how Java handles rounding:

> 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.

Honestly this is clear and concise. I have not found a comparable explanation for how it works in RPG; to be clear this is programming on an AS400 which uses RPG, but a much older version than what I believe the current standard is. However an explanation even for the modern implementation would be a start.

答案1

得分: 6

以下是翻译好的内容:

你发布的RPG代码与你的Java代码执行不同的操作。

Java代码将Double转换为Long,而RPG代码将一个带有6位小数的数字四舍五入到带有2位小数的数字。

特别是,elevensix是一个具有11位数字的数字,其中6位用于小数部分,5位用于整数部分;seventwo是一个具有7位数字的数字,其中2位用于小数部分,5位用于整数部分。

eval(h)是将elevensix的值复制到seventwo中,并使用“半递增”逻辑(这就是“h”的含义,如果没有它,小数部分将被截断)将其四舍五入到2位小数位。

根据RPG文档(也可以在PDF格式中找到),特别是这里的说明:

半递增是通过在结果字段中的最后指定的小数位置的右侧添加5(如果字段为负则为-5)来完成的。

对我来说,这似乎与Math.round所做的事情类似,但是泛化到任何小数位置。它还对应于Java Math RoundingMode.HALF_UP

由于您没有提供生成不一致性的实际示例,因此很难为您提供最终的解决方案。

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

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

您还可以考虑使用Apache Commons Math方法round,从实现上看,它几乎执行相同的操作。

您的问题也可能是由于Double的有限精度引起的,在这种情况下,您应该使用BigDecimals,参见此处

英文:

The RPG code you posted does a different thing than your Java code.

The Java code transform a Double to a Long, while the RPG code is rounding a number with 6 decimals to a number with 2 decimals.

In particular, elevensix is a number with 11 digits which 6 of them are for the decimal part and 5 of them for the integer part; seventwo is a number with 7 digits which 2 of them are for the decimal part and 5 of them for the integer part.

eval(h) is copying the value of elevensix into seventwo and rounding it to 2 decimal digits with "half-adjust" logic (that's what the "h" stand for, without it the decimals would be truncated).

From the 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.

Which to me seems similar to what Math.round does, but generalized to any decimal position.
Also it would correspond to the Java Math RoundingMode.HALF_UP.

Since you didn't provide some actual examples that generate the inconcistencies it's difficult to give you a definitive solution.

Anyway, that RPG code in Java could be replicated with BigDecimals with the method setScale like this:

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

You might also consider to use Apache Commons Math method round which, looking at the implementation, does pretty much the same thing.

Your problem could also be caused by the limited precision of Double and in that case you should just use BigDecimals, see https://stackoverflow.com/questions/3413448/double-vs-bigdecimal.

huangapple
  • 本文由 发表于 2020年8月10日 04:39:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/63331115.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定