2010-07-08 33 views
3

我试图分两位小数,然后显示结果。令人讨厌的是,这只发生在我们的服务器上,并且如果我在本地运行代码,它似乎工作得很好。这是我尝试运行在.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位..但我是不知道如何执行这种除法,因为它似乎将结果存储在内存中的十进制类型中,然后将其舍入并存储。我也试着直接将它转换为一个字符串,而不是将它存储在小数点中,但是它有相同的问题。

任何想法?我做了一些显然很愚蠢的事情(最有可能),还有更好的方法来执行这个计算吗?

+0

它可能是,你有一个32位服务器,但一个64位工作站? – cRichter 2010-07-08 13:56:10

+0

如果只是,它的64位基于xeon的服务器运行服务器2003 x64和.net 3.5 :( – Spud1 2010-07-08 14:06:05

+0

肯定要轮到28个地方,你需要看第29位,如果你要求27位,它仍然这样做吗? – James 2010-07-08 14:43:37

回答

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 
+0

我把这个标记为我的答案,因为在与我的同事交谈之后,这只发生在这个特定的情况下,我们可以应对精度的损失。已选择放入溢出的尝试/捕获,并转换为双倍,如果它现在发生..尽管如果有更好的答案,我宁愿把它放在未来:) – Spud1 2010-07-08 14:07:43

3

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

结果显然不在范围之外decimal,所以它在我看来就像你的服务器上发生了一些奇怪的事情。

有一件事要检查:Decimal.Round是抛出异常还是分裂本身?把它们放在单独的语句中以查明。

+0

感谢评论jon - 我最初有他们在单独的行,并尝试过与没有Decimal.Round,所以我敢肯定,舍入不是问题。它绝对是奇怪的,因为完全相同的代码工作在沙箱和我的桌面..frustrating问题;) – Spud1 2010-07-08 13:29:07

1

我通过反射体与来自看着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); 
} 

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

+0

我已经添加了一点更多的信息 - 之后,它回到其他代码是不相关的。我添加了一些日志记录来提取分割前的数字,这些都是它正在使用的数字。 目前我正在寻找由Tomas发布的双转换解决方案,因为我并不需要超过10/12 DP左右作为精度,而且看起来它可以工作..但需要测试它更多。 – Spud1 2010-07-08 13:44:51

+0

好的,它明显发生在部门内部。这很奇怪。你在本地和服务器上使用的是什么版本的框架?我会试着想想其他解决这个问题的方法,但这会很困难。我会看看我是否找不到'FCallDivide'方法的代码。 – 2010-07-08 13:57:30

1

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

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

相关问题