C#与COBOL十进制四舍五入

C#与COBOL十进制四舍五入,c#,decimal,rounding,cobol,C#,Decimal,Rounding,Cobol,我正在用C#重新编写一个COBOL程序,用于计算货币。然而,在最初的一些计算中,一些小数舍入是关闭的(与COBOL程序计算的不匹配) Decimal.Round(19.87*2.57,2)返回C#中的51.07(51.0659) COMPUTE varA=19.87*2.57返回COBOL格式的51.06 在这里,COBOL将数字向下舍入,但在其他情况下,当C#向下舍入时,COBOL将数字向上舍入。我不知所措 这是我必须做的第一个计算之一,所以一旦数字变大,它们就与COBOL输出越来越不同。(我

我正在用C#重新编写一个COBOL程序,用于计算货币。然而,在最初的一些计算中,一些小数舍入是关闭的(与COBOL程序计算的不匹配)

Decimal.Round(19.87*2.57,2)
返回C#中的51.07(51.0659)

COMPUTE varA=19.87*2.57
返回COBOL格式的51.06

在这里,COBOL将数字向下舍入,但在其他情况下,当C#向下舍入时,COBOL将数字向上舍入。我不知所措

这是我必须做的第一个计算之一,所以一旦数字变大,它们就与COBOL输出越来越不同。(我有一份测试数字的报告。)

我试过数学。圆,地板和天花板的两个类,以获得输出,我应该看到没有用


更新:我发现了我的问题所在。COBOL程序中计算中使用的许多字段都有9位小数,但结果存储在2位小数字段中。我是在截短后进行计算,而不是在截短前再进行计算。谢谢大家的帮助!每个答案都有用

首先,我认为您需要确定要从中迁移的COBOL版本。其次,任何时候都要小心
COMPUTE-ROUNDED
操作,因为它与您向我们展示的普通
COMPUTE
操作不同

一些有用的信息可以帮助你理解

要解决您的示例,请执行以下操作: 如果将C#计算值保留到小数点后三位,然后进行截断,则将镜像您提供的COBOL示例,而不会对其进行四舍五入。有关截断数字的帮助,请参阅


请注意,这假设您的所有COBOL都将以这种方式运行您必须验证这一点。

您显示的COBOL计算只是向下舍入(也称为截断)。中间结果将保留两位小数,如果使用计算器,您可能期望的多余值将消失

如果你不在新程序中复制这种行为,你将无法匹配这些数字

当然,COBOL程序可能是四舍五入的,但您必须找人对此进行调查

COMPUTE varA ROUNDED = 19.87 * 2.57
这将得到51.07,因为中间结果将是小数点后三位,那么如果第三位小数点是5-9,第二位小数点将增加一位,只有这样结果才会被截断

请注意,
COMPUTE
(带和不带
ROUNDED
)之间的差异对于确定正确的值非常重要。还要注意还有两个COBOL动词,
DIVIDE
MULTIPLY
,这两个动词的行为自然会有所不同,具体取决于数据是否取整。请注意,
添加
减去
,如果涉及不同的小数位数,也会

还要注意,计算越复杂,就越有可能在没有考虑实际使用的中间值的情况下对其进行编码。看看这两个,例如:

还要注意的是,当前的COBOL标准是1985年的标准,1989年对内在函数进行了修正和扩展。新标准还不完整,尽管其中的新元素已在一些编译器中实现,但实现不同类型舍入定义的编译器并不多。不管怎样,如果没有舍入,您将得到“向下舍入”。

COBOL

varA
似乎被定义为存储2个十进制位置。 由于未指定任何
取整
选项,因此乘法结果将被截断以适应此情况。这是默认行为

C#


使用
Math.Truncate(x*100m)/100m可以得到相同的结果

这里COBOL将数字向下舍入,但在其他情况下,它将在C#向下舍入的地方向上舍入。我不知所措
——这种(明显的)不一致给我带来了银行家取整的味道。请参阅统计/高斯舍入与“标准”舍入?看看您取得的进展。请注意(正如您从我的答案中的链接问题中所看到的),在计算中不需要大量的小数位数。如果小数位(可能)不包含有效数字,这意味着原始编码人员不知道如何有效地使用COMPUTE,并且从那以后就没有人敢碰它。可能表明你会在其他地方发现差异。如果需要再次询问,请确保包含所有字段定义。祝你好运。在Cobol中,你很可能使用固定长度的十进制数,而在C#中,你使用的是标准的浮点/双精度。2永远不会完全相同。COMPUTE是COBOL标准。任何没有标准计算的COBOL都不值得写在纸上。因此,对于这一点,不必知道它是哪种COBOL,当然,除此之外,这是非常有用的建议。这不会反映COBOL(即中间值只有两个小数),但它会给出相同的结果,而不会像其他答案所建议的那样进行愚蠢的乘法和除法:-)