C# 在.NET中除两个小数时出现溢出异常

C# 在.NET中除两个小数时出现溢出异常,c#,.net,decimal,division,C#,.net,Decimal,Division,我在尝试除以两个小数然后显示结果时遇到了一个问题。令人烦恼的是,这只发生在我们的服务器上,如果我在本地运行代码,它似乎工作得非常好。这就是我试图运行的代码 decimal dOne = -966.96M; decimal dTwo = 2300M; decimal dResult = Decimal.Round((dOne / dTwo), 28, MidpointRounding.AwayFromZero); 结果数字(由w

我在尝试除以两个小数然后显示结果时遇到了一个问题。令人烦恼的是,这只发生在我们的服务器上,如果我在本地运行代码,它似乎工作得非常好。这就是我试图运行的代码


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

decimal dResult = Decimal.Round((dOne / dTwo), 28, 
                               MidpointRounding.AwayFromZero);
结果数字(由windows计算器生成)为

-0.43346086952521739130434782608696

这始终会导致溢出异常:

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位..但我不确定如何执行此除法,因为它似乎将结果存储在内存中的十进制类型中,然后将其舍入并存储。我还尝试将其直接转换为字符串,而不是存储在十进制中,但这也有同样的问题

有什么想法吗?我是否做了一些明显愚蠢的事情(最有可能),是否有更好的方法来执行此计算?

应该运行良好。该部门不保证返回准确的版本-例如,1/3m可以正常工作

结果显然不在十进制范围之外,所以在我看来,您的服务器上似乎发生了一些奇怪的事情


需要检查的一件事是:抛出异常的是
Decimal.Round
,还是除法本身?将它们放在单独的语句中找出答案。

在计算前尝试转换为
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

我通过反射器查看了
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中的执行方式看出,溢出异常将以许多不同的方式生成。代码相当复杂。如果你能构建一个简短但完整的程序来演示这个问题,我会把它作为bug提交给微软。这些输入中可能有某种位模式会混淆算法。

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


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

感谢jon的评论-我最初将它们放在单独的行中,并尝试了使用和不使用Decimal.Round,因此我非常确定舍入不是问题。这确实很奇怪,因为相同的代码在沙盒和我的桌面上都能正常工作。。令人沮丧的问题;)我添加了更多的信息-之后,它会返回到其他不相关的代码。我添加了一些日志来提取除法之前的数字,这些就是它正在使用的数字。目前,我正在看Tomas发布的双转换解决方案,因为我并不需要超过10/12 DP左右的精度,看起来它会起作用。但需要更多的测试。好的,这显然是在部门内部发生的。这很奇怪。您在本地和服务器上使用的框架版本是什么?我将尝试想出其他方法来解决这个问题,但这将是困难的。我将查看是否找不到
FCallDivide
方法的代码。可能是因为您有一台32位服务器,但有一台64位工作站吗?如果只是,它是一台运行server 2003 x64和.net 3.5的基于64位xeon的服务器:(当然要凑到28位,你需要看第29位。如果你要27位,它还能凑到吗?我把这作为我的答案,因为在和我的同事讨论后,这只发生在这个特定的情况下,我们可以应对精度的损失。我选择了尝试/捕捉溢出,如果发生了,就转换为双精度。)ns现在…虽然如果有更好的答案,我宁愿在将来说:)