在C#

时间:2017-01-08 06:48:37

标签: c# casting precision

我试图理解为什么在计算4 * Math.Pow(256, 6)并转换为十进制时我失去了精确度。这是一个模糊不清的错误的原因,虽然我已经解决了这个问题,但我试图了解它的发生情况。

我原来的代码是:

    (decimal)(num * Math.Pow(256, exp))

这有时导致错误的数字(如果num>=4exp>=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]

0 个答案:

没有答案