将浮点数转换为双精度浮点数再转换回浮点数。

4

能否在不失精度的情况下将浮点数转换为双精度,然后再转回去?我的意思是第一个浮点数应该与结果浮点数完全相同,位对位地匹配。


它们都有自己的精度,你可以将其中一个转换为另一个,但不能反过来。 - MakePeaceGreatAgain
2个回答

5

是的,我们可以进行测试:

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;
    }
}

在我的电脑上,在Release模式下,没有使用调试器(从Visual Studio按Ctrl+F5),大约需要2分钟。
大约有40亿个不同的float值。我将它们强制转换并将它们转换为int以进行二进制检查。请注意,NaN值是“特殊”的。IEEE754标准有多个值用于NaN,但.NET将它们“压缩”为单个NaN值。因此,您可以创建一个NaN值(手动通过位操作),该值无法正确地转换回来和转换。标准的NaN值被正确转换,PositiveInfinity和NegativeInfinity,+0和-0也是如此。

我正在考虑写类似的东西 :) 非常感谢。 - apocalypse
@zgnilec “有趣”的部分是如何找到一个浮点数的“下一个”浮点数。如果你想知道浮点数之间的“距离”,这将非常有用(我已经有了Ieee754类……我在一年前尝试IEEE754时就写过它)。 - xanatos

0

是的,由于每个浮点数都可以精确地表示为双精度浮点数,因此往返转换将给您与开始时完全相同的精确值。

在您要求它们按位完全相同时,有一个可能的技术例外:有多个位模式对应于NaN值(这通常称为“NaN有效负载”)。据我所知,没有严格的要求必须保留它:您仍将获得NaN,只是可能会稍有不同。


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