将float转换为int而不进行任何转换?

时间:2011-11-07 14:13:46

标签: c# casting bit-manipulation

我通过手动转换和移动值将各种类型写入字节流。我发现这比使用BitConverter或BinaryWriter快三倍。

我的问题是花车。我需要将它们转换为int以便对它们执行移位操作,但是任何转换为​​int都将导致带截断的隐式转换等。我希望保持精确的二进制表示相同。这可能吗?

例如。我希望能够做到:

byte[] bytes = new byte[4];
float myFloat = 32.2;

//following won't compile as can't shift floats.
bytes [0] = (byte)myFloat;
bytes [1] = (byte)(myFloat >> 8);
bytes [2] = (byte)(myFloat >> 16);
bytes [3] = (byte)(myFloat >> 24);

3 个答案:

答案 0 :(得分:15)

以下内容不需要不安全的代码,并且证明可以正常工作(我在各种.NET版本中使用了多年):

[StructLayout(LayoutKind.Explicit)]
public struct FloatAndUIntUnion
{
    [FieldOffset(0)]
    public uint  UInt32Bits;
    [FieldOffset(0)]
    public float FloatValue;
}


FloatAndUIntUnion f2i = default(FloatAndUIntUnion);
f2i.FloatValue = aFloat;    // write as float
uint i = f2i.UInt32Bits;    // read back as int

请注意,float→int方向可以更简单:

int i = aFloat.GetHashCode();

然而,由于没有记录,它更加模糊 (根据MSDN),虽然由this post确认。 (也就是说,2006年的行为与2013年相同, 我认为将来没有理由改变它 - 但可能会发生, 而且我不确定它是否符合后向不兼容的条件 改变与否。)

答案 1 :(得分:6)

您可以使用double代替float吗?

double doubleValue = 32.2;
long setofBits = BitConverter.DoubleToInt64Bits(doubleValue);

编辑:回复评论

我相信使用BitConverter没有任何开销,使用Reflector我们可以看到它的实现非常简单:

public static unsafe long DoubleToInt64Bits(double value)
{
    return *(((long*) &value));
}

答案 2 :(得分:5)

float myFloat = 0.124112f;
float[] floats = new[] { myFloat };
byte[] bytes = new byte[4];
Buffer.BlockCopy(floats, 0, bytes, 0, 4);

编辑:DoubleToInt64Bits相比,它在我的机器上慢了4倍,这与DoubleToInt64Bits的极端简单性相比,因其阵列性质和不可避免的开销而有意义实施