在.NET中除两位小数时出现溢出异常
我在尝试除以两位小数然后显示结果时遇到问题。令人烦恼的是,这只发生在我们的服务器上,如果我在本地运行代码,它似乎工作得很好。这是我尝试运行的代码
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 位..但我不确定如何执行此除法,因为它似乎将结果以十进制类型存储在内存中,然后四舍五入并存储它。我也尝试过将其直接转换为字符串而不是将其存储为十进制,但这也存在同样的问题。
有什么想法吗?我是否做了一些明显愚蠢的事情(最有可能),是否有更好的方法来执行此计算?
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
-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. 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试在计算之前转换为
double
,然后如果需要,再转换为decimal
:Try converting to
double
before calculating, and back todecimal
afterwards if you need:应该运行得很好。该除法不能保证返回完全准确的版本 - 例如,1 / 3m 就可以了。
结果显然不在
十进制
的范围之外,所以在我看来,您的服务器上发生了一些奇怪的事情。要检查的一件事是:是
Decimal.Round
引发了异常,还是除法本身?将它们放入单独的语句中以找出答案。That should run fine. The division isn't guaranteed to return the exactly accurate version - for example, 1 / 3m works fine.
The result clearly isn't outside the range of
decimal
, so it looks to me like something weird is going on on your server.One thing to check: is it
Decimal.Round
that's throwing the exception, or the division itself? Put them into separate statements to find out.如果它发生在您的服务器上(您无法调试)。您真的确定问题出在这些范围内吗?
也许您可以仅在单个 Decimal.Round 语句周围放置一个 try-catch 语句,并返回一些奇怪的值。您可以再次在服务器上运行这段代码,看看这个 catch 语句是否真的被调用,或者异常是否可能发生在其他地方。
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. 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.
我通过 Reflector 查看了 Decimal.Round,从我所看到的来看,它永远不会抛出 OverflowException,所以我打赌异常来自除法。您可以编辑您的答案以包含堆栈跟踪吗?
另外,您绝对确定分子和分母与您所写的完全一样吗?当异常发生时,尝试将它们跟踪到控制台或日志文件。
您可以执行以下操作:
编辑: 我想我在 SSCLI 中找到了
FCallDivide
的代码。然而,在 .NET Framework 的发行版本中可能会有所不同,但我可以从 SSCLI 中的完成方式看出,无论如何,溢出异常将以多种不同的方式生成。代码相当复杂。如果您可以构建一个简短但完整的程序来演示该问题,我会将其作为错误提交给 Microsoft。这些输入中可能存在某种使算法感到困惑的位模式。I looked at
Decimal.Round
via Reflector and from what I see it does not ever throwOverflowException
so I am betting the exception is coming from the division. 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:
Edit: I think I found the code to
FCallDivide
in the SSCLI. 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. 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. It is possible that there is a certain bit pattern in those inputs that is confusing the algorithm.