英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论