将整数位转换为浮点数位

5
我正在创建一个缓冲区,在其中我可以完全消除TCP-Segmentation带来的问题,该缓冲区将读取/写入横幅。唯一遇到的问题是浮点变量,除了浮点数之外,其他都正常工作。我找不到有关如何将int32位转换为浮点数的任何信息。
当将浮点数转换为int位时,使用以下方法(直接从Java源代码中提取并转换)。
private int floatToIntBits(float value)
{
    int result = BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
    if (((result & 0x7F800000) == 0x7F800000) && (result & 0x80000000) != 0)
        result = 0x7fc00000;
    return result;
}

然而,现在我需要做相反的操作,不幸的是,在BitConverter类中没有任何适用于float类型的函数。

我在JavaDocs中也找不到太多信息,也没有任何我可以个人利用的信息,您可以在这里找到相关信息。

8个回答

11

令人不爽的是,如果您正在使用 doublelong,那么有 BitConverter.DoubleToInt64BitsBitConverter.Int64BitsToDouble。我真的不知道为什么没有 Single / Int32 的等效物,因为它会强制您在堆上创建一个无意义的 byte[](甚至不允许您传递预先存在的缓冲区)。

如果您愿意使用 unsafe 代码,实际上可以在简单的数据 thunk 中完成所有操作,而无需进行任何方法调用或数组:

public static unsafe int SingleToInt32Bits(float value) {
    return *(int*)(&value);
}
public static unsafe float Int32BitsToSingle(int value) {
    return *(float*)(&value);
}

很遗憾,由于这是Unity3D的客户端API,我不能使用不安全的代码。我以前找到过这个解决方案,但Unity不允许它。不过还是谢谢你的回复,对于一个简单的解决方案点赞。 - Hobbyist
@Christian.tucker 是的,那真的很烦人;我做了很多位操作(我维护几个二进制序列化器和其他网络实用库),因此当unsafe不被允许时,这对我来说非常困难。 - Marc Gravell

11

BitConverter会产生一些额外的开销和不必要的缓存。这种解决方案几乎和不安全转换一样快:

[StructLayout(LayoutKind.Explicit)]
struct FloatToInt 
{
    [FieldOffset(0)]private float f;
    [FieldOffset(0)]private int i;
    public static int Convert(float value)
    {
        return new FloatToInt { f = value }.i;
    }
}

这是一个很棒的技巧,谢谢您。 - NSJacob1
1
这个不需要使用static FloatToInt,这么做会使得其不必要的线程不安全。在Convert(float value)中只需返回new FloatToInt { f = value }.i;即可。由于FloatToInt是一个结构体,使用new FloatToInt { }不会在堆上分配任何空间。 - dbc
Bitconverter在.net core 7中并不创建缓冲区,至少目前是这样的。public static unsafe int SingleToInt32Bits(float value) => *((int*)&value); public static unsafe float Int32BitsToSingle(int value) => *((float*)&value); - Warty
@Warty 这是关于BitConverter.GetBytes(value)的问题。当时还没有直接的转换方法,所以你必须先获取字节。 - Aberro

5

使用BitConverter.ToSingle方法:

int i = ...;
float f = BitConverter.ToSingle(BitConverter.GetBytes(i), 0);

2
关键字 float 是数据类型 System.Single 的别名。
您可以使用 BitConverter.ToSingle 将四个字节转换为 float

我从未听说过那个别名,非常有趣。 - Hobbyist
这样使用是否正确?byte ch1 = ReadByte(); byte ch2 = ReadByte(); byte ch3 = ReadByte(); byte ch4 = ReadByte(); return BitConverter.ToSingle(new byte[] { ch1, ch2, ch3, ch4 }, 0); - Hobbyist
2
如果是网络编程,我不一定会推荐这样做,因为那些烦人的 byte[]。我已经单独添加了一些替代方案。 - Marc Gravell

2

现在我们可以针对.NET Core简单地使用BitConverter.SingleToInt32Bits()BitConverter.Int32BitsToSingle()了!


1
使用 System.Runtime.CompilerServices.Unsafe NuGet 包
Unsafe.As<float, int>(ref value);

将一个浮点数转换为整数。
和。
Unsafe.As<int, float>(ref value);

将一个整数转换为浮点数。

0

0

自从 .NET Core 2.0 版本以来,我们就拥有了一个内置的 API 来实现这个功能,BitConverter.Int32BitsToSingle

float f = BitConverter.Int32BitsToSingle(i);

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