是否有任何功能或正确的方法将十进制数解析为指数

时间:2019-05-16 13:33:49

标签: c# performance decimal exponential

我正在尝试解析 C# decimal类型为我自己的 Decimal类型,其类型为{{1 }}和significant。我尝试过:

exponent

但是我认为它会很慢。

1 个答案:

答案 0 :(得分:0)

您可以尝试decimal.GetBits(),例如

  public static MyType.Decimal FromDecimal(decimal decimalValue) {
    int[] parts = decimal.GetBits(decimalValue);

    int sign = 1 - 2 * (parts[3] >> 31 & 1);
    long mantissa = ((((long)parts[1]) << 32) | (((long)parts[0]))) * sign;
    int exponent = -((parts[3] >> 16) & 0xFF);

    return MyType.Decimal() {
      Significand = mantissa, 
      Exponent    = exponent
    };
  }

但是要小心:decimal使用 96位尾数(请注意,我们{em>忽略了parts[2] abscence < / em>),这就是long Significand太短(long 64位

的原因

演示:

  decimal[] tests = new decimal[] {
    0m,
    10m,
    100m,
    0.01m,
    123e-1m,
   -3m,
    123456789e4m,
    123456789e-4m,
    1234567890123456m,
    1234567890123456e4m // 12345678901234560000 > long.MaxValue (9223372036854775807)
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => {
      int[] parts = decimal.GetBits(test);

      int sign = 1 - 2 * (parts[3] >> 31 & 1);
      long mantissa = ((((long)parts[1]) << 32) | (((long)parts[0]))) * sign;
      int exponent = -((parts[3] >> 16) & 0xFF);

      return $"{test,20} == {mantissa}e{exponent}";
    })); 

结果:

                   0 == 0e0
                  10 == 10e0
                 100 == 100e0
                0.01 == 1e-2
                12.3 == 123e-1
                  -3 == -3e0
       1234567890000 == 1234567890000e0
          12345.6789 == 123456789e-4
    1234567890123456 == 1234567890123456e0
12345678901234560000 == -350295040e0        -- mantissa is 96 bit, doesn't fit 64-bit long