最近我试图解决程序中的一个bug,并意识到问题出在下面的代码中(类型不是字节,但假设这个问题的类型不能大于字节,因为某些组合可能会导致溢出):
long GetValue(byte x, byte y, byte z) {
return (long)Math.Pow(x, y) * z;
}给定的示例值为:x= 27,y= 12,z=7
然后:
a = 27 ^ 12 = 150,094,635,296,999,121
r = a * 7 = 1,050,662,447,078,993,847但是,C#.NET代码将提供:
a = 27 ^ 12 = 150,094,635,296,999,136
r = a * 7 = 1,050,662,447,078,993,952线索在Math.Pow函数中,该函数将返回表示为:
1.5009463529699914E+17这是因为Math.Pow函数只对doubles存在,并且doubles的不精确度超过了某个小数值。由于结果越来越接近long.MaxValue,因此不精确的浮点数学运算会影响强制转换产生的长值。
对于longs,没有等效的Math.Pow函数。有些东西告诉我,理由是因为在引擎盖下,不管你如何表达,长整型和双精度型都是64位的数字。然而(在我看来) longs不应该使用浮点数学。
这是否意味着CPU不能对32位以上的非小数值执行精确计算?对我来说,这似乎是非常不可能的,因为Windows计算器可以正确地计算出这个数学。
这样的问题应该如何在.NET中解决呢?我在某种程度上假设我遗漏了某个函数。
(我通过更改解决方案设计的方法解决了最初的问题,不再需要这些代码,但我想我还是要发布这个问题,因为它很有趣。)
问候你,罗伯。
发布于 2016-09-20 17:49:43
您可以使用BigInteger类处理任意精度的整数。这是您的问题的规范解决方案。
如果你不需要大于long.MaxValue的数字,你也可以给自己写一个简单的幂函数。
CPU使用固定大小的整数。任意大小的整数是一种软件解决方案。
https://stackoverflow.com/questions/39590835
复制相似问题