从double中提取尾数和指数的c#方法

33
有没有一种简单的方法在C#(或.NET)中从double类型中获取尾数和指数?我找到了这个例子,使用谷歌搜索(参考链接),但是我不确定它有多健壮。在将来的框架版本中,double的二进制表示是否会改变等?我找到的另一个选择是使用System.Decimal代替double,并使用Decimal.GetBits()方法来提取它们。有什么建议吗?
2个回答

38

二进制格式不应该改变 - 这肯定会对现有规范造成破坏性影响。它被定义为IEEE754 / IEC 60559:1989格式,就像Jimmy所说的那样。(C# 3.0语言规范第1.3节; ECMA 335第8.2.2节)。DoubleConverter中的代码应该是良好和健壮的。

为了以后参考,示例中相关代码的部分是:

public static string ToExactString (double d)
{
    …

    // Translate the double into sign, exponent and mantissa.
    long bits = BitConverter.DoubleToInt64Bits(d);
    // Note that the shift is sign-extended, hence the test against -1 not 1
    bool negative = (bits & (1L << 63)) != 0;
    int exponent = (int) ((bits >> 52) & 0x7ffL);
    long mantissa = bits & 0xfffffffffffffL;

    // Subnormal numbers; exponent is effectively one higher,
    // but there's no extra normalisation bit in the mantissa
    if (exponent==0)
    {
        exponent++;
    }
    // Normal numbers; leave exponent as it is but add extra
    // bit to the front of the mantissa
    else
    {
        mantissa = mantissa | (1L << 52);
    }

    // Bias the exponent. It's actually biased by 1023, but we're
    // treating the mantissa as m.0 rather than 0.m, so we need
    // to subtract another 52 from it.
    exponent -= 1075;

    if (mantissa == 0) 
    {
        return negative ? "-0" : "0";
    }

    /* Normalize */
    while((mantissa & 1) == 0) 
    {    /*  i.e., Mantissa is even */
        mantissa >>= 1;
        exponent++;
    }

    …
}

当时这些评论对我来说很有意义,但现在我肯定需要花一些时间去思考它们。在最初的部分之后,您可以获得“原始”的指数和尾数 - 其余代码只是帮助更简单地处理它们。


有人可以发布类似的代码将“decimal”转换为尾数和指数吗? 我想应该使用“Decimal.GetBits()”方法。 - Oleg Vazhnev
更新:我在这里找到了一个计算尾数的例子,但指数没有被计算。https://dev59.com/0nRA5IYBdhLWcg3w9y10#764102 - Oleg Vazhnev
@JonSkeet 对,我在谈论另一个问题https://dev59.com/0nRA5IYBdhLWcg3w9y10#764102。我在这个问题中提问,因为当我发表第一条评论时,我没有找到这个另外的“decimal”问题。 - Oleg Vazhnev
@SlippD.Thompson:如果尾数不为0,则至少会有一个非零数字。我怀疑如果我去掉了这个特殊情况,它最终会返回空字符串而不是“0”,如果你传入0的话。 - Jon Skeet
1
@Michael:我怀疑你对指数的处理方式与我相反,仅此而已。(左移还是右移) - Jon Skeet
显示剩余16条评论

1

该表示法是IEEE标准,不应更改。

https://msdn.microsoft.com/en-us/library/system.double(v=vs.110).aspx

Double类型符合IEC 60559:1989(IEEE 754)二进制浮点算术标准。
编辑:十进制具有getBits而双精度浮点数没有的原因是十进制保留有效数字。3.0000m == 3.00m,但指数/尾数实际上是不同的。我认为浮点数/双精度浮点数是唯一表示的。

在C/C++中,double不一定是64位。我曾经在几个系统上工作过,其中它是32位(即与float相同)。C#有所不同吗? - Judge Maygarden
3
是的,规范中定义为64位。关于C/C++中double(以及long/int/long long)的混乱问题,那是个很好的观点。 - Jimmy
2
@Jimmy,如果C#能够支持至少一半的C/C++支持平台,那么你才能谈论C/C++中的惨败。 - Slava
1
链接需要更新。 - Xonatron
编辑队列已满,因此我将在此处放置更新后的链接:https://learn.microsoft.com/en-us/dotnet/api/system.double - pogosama

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接