在.NET中分割两个小数时溢出异常

时间:2010-07-08 13:16:31

标签: c# .net decimal division

我在尝试划分两位小数然后显示结果时出现问题。令人讨厌的是,这只发生在我们的服务器上,如果我在本地运行代码,它似乎工作得很好。这是我试图运行的代码


decimal dOne = -966.96M;
decimal dTwo = 2300M;

decimal dResult = Decimal.Round((dOne / dTwo), 28, 
                               MidpointRounding.AwayFromZero);

结果数字(由Windows计算器生成)是

-0.43346086956521739130434782608696

这总是会导致溢出异常:

System.OverflowException: Value was either too large or too small for a Decimal.
   at System.Decimal.FCallDivide(Decimal& result, Decimal d1, Decimal d2)
   at System.Decimal.op_Division(Decimal d1, Decimal d2)

这有点意义,因为结果数字超过32位小数,小数只能容纳28个位置..但我不知道如何执行此除法,因为它似乎存储结果在内存中的十进制类型中,在将其四舍五入并存储之前。我也尝试将它直接转换为字符串,而不是将其存储在小数中,但这也存在同样的问题。

有什么想法吗?我做过一些显然很愚蠢的事情(最有可能)并且有更好的方法来执行此计算吗?

4 个答案:

答案 0 :(得分:4)

尝试在计算前转换为double,如果需要,请稍后返回decimal

decimal dOne = -966.96M;
decimal dTwo = 2300M;

double one = (double)dOne;
double two = (double)dTwo;

double result = one / two;

decimal dResult = (decimal)result; // Additional rounding may be necessary

答案 1 :(得分:3)

应该运行良好。该部门无法保证返回完全准确版本 - 例如,1 / 3m工作正常。

结果显然不在decimal范围之外,因此我觉得你的服务器上发生了一些奇怪的事情。

要检查的一件事是:它是Decimal.Round抛出异常还是分裂本身?将它们放在单独的陈述中以找出答案。

答案 2 :(得分:1)

我通过Reflector查看了Decimal.Round,并且从我看到它不会抛出OverflowException所以我打赌异常来自该部门。你能编辑你的答案以包括堆栈跟踪吗?

另外,你绝对肯定分子和分母与你所写的一模一样吗?发生异常时,尝试将它们跟踪到控制台或日志文件。

你可以这样做:

decimal dOne = -966.96M; 
decimal dTwo = 2300M;  
try
{
  decimal dResult = Decimal.Round((dOne / dTwo), 28, MidpointRounding.AwayFromZero); 
}
catch (OverflowException)
{
  Console.WriteLine(dOne);
  Console.WriteLine(dTwo);
}

修改:我认为我在SSCLI中找到了FCallDivide的代码。但是,在.NET Framework的发布版本中可能会有所不同,但我可以从SSCLI中的方式看出,无论如何都会以很多不同的方式生成溢出异常。代码非常复杂。如果您可以构建一个简短但完整的程序来演示问题,我会将其作为错误提交给Microsoft。这些输入中可能存在某种混淆算法的位模式。

答案 3 :(得分:1)

如果它发生在您的服务器上(您无法调试)。你真的确定问题在这些方面吗?

也许你可以只在单个Decimal.Round语句中放置一个try-catch语句,然后给出一些奇怪的值。此代码可以再次在您的服务器上运行,以查看是否真的调用了此catch语句,或者是否可能在其他地方发生异常。