我试图理解为什么在计算4 * Math.Pow(256, 6)
并转换为十进制时我失去了精确度。这是一个模糊不清的错误的原因,虽然我已经解决了这个问题,但我试图了解它的发生情况。
我原来的代码是:
(decimal)(num * Math.Pow(256, exp))
这有时导致错误的数字(如果num>=4
和exp>=6
),但通过将其更改为:
num * (decimal)Math.Pow(256, exp)
示例:
4 * Math.Pow(256, 6) == 1125899906842624 (double)
(decimal)(4 * Math.Pow(256, 6)) == 1125899906842620 (decimal)
4 * (decimal)Math.Pow(256, 6) == 1125899906842624 (decimal)
让我感到困惑的是,如果num<=3
它不会这样做:
1 * Math.Pow(256, 6) == 281474976710656 (double)
(decimal)(1 * Math.Pow(256, 6)) == 281474976710656 (decimal)
1 * (decimal)Math.Pow(256, 6) == 281474976710656 (decimal)
这里发生了什么?
修改:我注意到可能存在相关问题,因为Math.Exp(256,exp)
exp > 6
也不准确(甚至在转换为十进制之前):
exp Math.Pow(256,exp) Expected value
--- ----------------------- -----------------------
5 1099511627776 1099511627776
6 281474976710656 281474976710656
7 72057594037927900 72057594037927936
8 18446744073709600000 18446744073709551616
9 4722366482869650000000 4722366482869645213696
这意味着我放弃了尝试使用这种方法,并且刚刚定义:
private static readonly Dictionary<int, decimal> PowersOf256 = new Dictionary<int, decimal>()
{
{0, 1m},
{1, 256m},
{2, 65536m},
{3, 16777216m},
{4, 4294967296m},
{5, 1099511627776m},
{6, 281474976710656m},
{7, 72057594037927936m},
{8, 18446744073709551616m},
{9, 4722366482869645213696m},
{10, 1208925819614629174706176m},
{11, 309485009821345068724781056m},
// 256^12 is > decimal.MaxValue
};
现在只需使用:
num * PowersOf256[exp]