转换 float -> double -> float

Convert float -> double -> float

是否可以将 float 转换为 double,然后返回而不丢失精度?我的意思是第一个浮点数应该像结果浮点数一样精确。

是的,我们可以测试它:

float fl = float.NegativeInfinity;

long cycles = 0;

while (true)
{
    double dbl = fl;
    float fl2 = (float)dbl;

    int flToInt1 = new Ieee754.Int32SingleConverter { Single = fl }.Int32;
    int flToInt2 = new Ieee754.Int32SingleConverter { Single = fl2 }.Int32;

    if (flToInt1 != flToInt2)
    {
        Console.WriteLine("\nDifferent: {0} (Int32: {1}, {2})", fl, flToInt1, flToInt2);
    }

    if (fl == 0)
    {
        Console.WriteLine("\n0, Sign: {0}", flToInt1 < 0 ? "-" : "+");
    }

    if (fl == float.PositiveInfinity)
    {
        fl = float.NaN;
    }
    else if (float.IsNaN(fl))
    {
        break;
    }
    else
    {
        fl = Ieee754.NextSingle(fl);
    }

    cycles++;

    if (cycles % 100000000 == 0)
    {
        Console.Write(".");
    }
}

Console.WriteLine("\nDone");
Console.ReadKey();

和实用程序 类:

public static class Ieee754
{
    [StructLayout(LayoutKind.Explicit)]
    public struct Int32SingleConverter
    {
        [FieldOffset(0)]
        public int Int32;

        [FieldOffset(0)]
        public float Single;
    }

    public static float NextSingle(float value)
    {
        int bits = new Int32SingleConverter { Single = value }.Int32;

        if (bits >= 0)
        {
            bits++;
        }
        else if (bits != int.MinValue)
        {
            bits--;
        }
        else
        {
            bits = 0;
        }

        return new Int32SingleConverter { Int32 = bits }.Single;
    }
}

在我的电脑上,在发布模式下,没有调试器(来自 Visual Studio 的 Ctrl+F5),大约需要 2 分钟。

大约有 40 亿个不同的 float 值。我将它们投射并将它们转换为 int 以对它们进行二进制检查。请注意 NaN 值为 "particular"。 IEEE754 标准对 NaN 有多个值,但 .NET "compresses" 它们只有一个 NaN 值。因此,您可以创建一个无法正确来回转换的 NaN 值(手动,通过位操作)。 "standard" NaN 值已正确转换,因此 PositiveInfinityNegativeInfinity+0-0

是的,因为每个浮点数都可以精确地表示为双精度数,所以往返将为您提供开始时的确切值。

对于您要求它们逐位相同的要求,有一个可能的技术例外:有多个位模式对应于 NaN 值(这通常称为 "NaN payload")。据我所知,没有严格要求保留它:你仍然会得到一个 NaN,只是可能略有不同。