首页 > 解决方案 > 是否有任何功能或正确的方法可以将十进制数解析为指数

问题描述

我正在尝试将C#类型解析为 我自己的类型,该类型具有且只有。我试过这个: decimal Decimalsignificantexponent

    public static MyType.Decimal FromDecimal(decimal decimalValue)
    {
        decimal tempValue = decimalValue;
        int exponent = 0;

        while ((long) (tempValue) < decimalValue)
        {
            tempValue *= 10;
            decimalValue *= 10;
            exponent--;
        }

        return new MyType.Decimal()
        {
            Significand = (long)tempValue,
            Exponent = exponent
        };
    }

    public class Decimal
    {
        public long Significand;
        public int Exponent;
    }

但在我看来,它会很慢

标签: c#performancedecimalexponential

解决方案


您可以尝试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 位尾数(请注意,我们忽略了它就是为什么太短(仅64 位parts[2]long Significandlong

演示:

  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

推荐阅读