简体   繁体   English

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

[英]Overflow Exception when dividing two decimals in .NET

I'm having an issue trying to divide two decimals and then display the result. 我试图划分两位小数然后显示结果有问题。 Annoyingly this is only happening on our server, and it appears to work perfectly fine if I run the code locally. 令人讨厌的是,这只发生在我们的服务器上,如果我在本地运行代码,它似乎工作得很好。 This is the code that I am trying to run 这是我试图运行的代码


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

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

The resulting number (as generated from windows calculator) is 结果数字(由Windows计算器生成)是

-0.43346086956521739130434782608696 -0.43346086956521739130434782608696

This always results in an overflow exception: 这总是会导致溢出异常:

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)

This does kind of make sense as the resulting number is over 32 decimal places long, and a decimal can only hold up to 28 places..but I am not sure how to perform this division as it appears to be storing the result in the decimal type in memory, before rounding it off and storing it. 这有点意义,因为结果数字超过32位小数,一个十进制最多只能容纳28个位置..但我不知道如何执行此除法,因为它似乎将结果存储在十进制中键入内存,然后将其四舍五入并存储。 I've also tried converting it directly to a string rather than storing it in a decimal, but that has the same problem. 我也尝试将它直接转换为字符串,而不是将其存储在十进制中,但这有同样的问题。

Any ideas? 有任何想法吗? Have I done something obviously silly (most probably) and is there a better way to perform this calculation? 我做过一些显然很愚蠢的事情(最有可能)并且有更好的方法来执行此计算吗?

Try converting to double before calculating, and back to decimal afterwards if you need: 在计算之前尝试转换为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

That should run fine. 应该没问题 The division isn't guaranteed to return the exactly accurate version - for example, 1 / 3m works fine. 该部门不保证返回准确准确的版本-例如,1 /3米工作正常。

The result clearly isn't outside the range of decimal , so it looks to me like something weird is going on on your server. 结果显然不在decimal 范围之外,所以在我看来你的服务器上发生了一些奇怪的事情。

One thing to check: is it Decimal.Round that's throwing the exception, or the division itself? 要检查一件事:是Decimal.Round抛出异常,还是分裂本身? Put them into separate statements to find out. 将它们放入单独的陈述中以找出答案。

I looked at Decimal.Round via Reflector and from what I see it does not ever throw OverflowException so I am betting the exception is coming from the division. 我通过Reflector查看了Decimal.Round ,并且从我看到它不会抛出OverflowException所以我打赌异常来自该部门。 Can you edit your answer to include the stack trace? 你能编辑你的答案以包括堆栈跟踪吗?

Also, are you absolutely certain that the numerator and denominator are exactly as you have written? 另外,你是否绝对确定分子和分母与你所写的一模一样? Try tracing the them to the console or a log file when the exception occurs. 发生异常时,尝试将它们跟踪到控制台或日志文件。

You could do something like this: 你可以这样做:

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);
}

Edit: I think I found the code to FCallDivide in the SSCLI. 编辑:我想我在SSCLI中找到了FCallDivide的代码。 However, it is likely to be different in the release version of the .NET Framework, but I can see from the way it was done in the SSCLI anyway that an overflow exception will be generated in a lot of different ways. 但是,在.NET Framework的发布版本中可能会有所不同,但我可以从SSCLI中的方式看出,无论如何都会以很多不同的方式生成溢出异常。 The code is quite complicated. 代码非常复杂。 If you can construct a short but complete program demonstrating the problem I would submit it as a bug to Microsoft. 如果您可以构建一个简短但完整的程序来演示问题,我会将其作为错误提交给Microsoft。 It is possible that there is a certain bit pattern in those inputs that is confusing the algorithm. 这些输入中可能存在某种混淆算法的位模式。

If it happens on your sever (where you can't debug). 如果它发生在您的服务器上(您无法调试)。 Are you really sure that the problem is within these lines? 你真的确定问题在这些方面吗?

Maybe you can put a try-catch statement around only the single Decimal.Round statement and giving back some weird value instead. 也许你可以只在一个Decimal.Round语句周围放一个try-catch语句,然后给出一些奇怪的值。 This code could you run on your server again to see if this catch statement really gets called or if the Exception maybe happens somewhere else. 此代码可以再次在您的服务器上运行,以查看是否真的调用了此catch语句,或者是否可能在其他地方发生异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM