5

I'm in the process of creating a buffer that will read/write in a banner in which I can completely eradicate the problems that comes with TCP-Segmentation. The only problem I've ran into is the float variable, everything else works fine, besides for the float. I can't find any information on how to convert int32 bits into a float.

When converting a float to int bits, the following method is used (Ripped straight out of java's source code, and converted)

private int floatToIntBits(float value)
{
    int result = BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
    if (((result & 0x7F800000) == 0x7F800000) && (result & 0x80000000) != 0)
        result = 0x7fc00000;
    return result;
}

However, now I need to do the opposite, unfortunately, there isn't any functions in the BitConverter class that works with float.

I can';t find much information in the JavaDocs either, not any that I can personally make use of, You can find info here.

abatishchev
  • 95,331
  • 80
  • 293
  • 426
Hobbyist
  • 15,138
  • 9
  • 42
  • 93

8 Answers8

10

Vexingly, if you were using double and long, there is BitConverter.DoubleToInt64Bits and BitConverter.Int64BitsToDouble. I have genuinely no idea why there aren't Single / Int32 equivalents, as it forces you to create a pointless byte[] on the heap (it doesn't even let you pass in a pre-existing buffer).

If you are happy to use unsafe code, you can actually do it all in a simply data thunk, without any method calls or arrays:

public static unsafe int SingleToInt32Bits(float value) {
    return *(int*)(&value);
}
public static unsafe float Int32BitsToSingle(int value) {
    return *(float*)(&value);
}
Marc Gravell
  • 976,458
  • 251
  • 2,474
  • 2,830
  • Unfortunately, as this is a client-api for Unity3D, I can't use unsafe code, I've found this solution before and Unity disallowed it. Thanks for the reply though, +1 for a simple solution. – Hobbyist Dec 02 '14 at 13:34
  • @Christian.tucker yeah, that is annoying; I do a lot of bit work (I maintain several binary serializers and other network utility libraries), so this hurts me *a lot* when `unsafe` is not allowed – Marc Gravell Dec 02 '14 at 23:16
6

BitConverter creates some overhead and unnecessary buffer. This solution is almost as fast as unsafe conversion:

[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;
    }
}
dbc
  • 91,441
  • 18
  • 186
  • 284
Aberro
  • 540
  • 5
  • 9
  • This is a great technique, thanks for this – NSJacob1 Jul 30 '21 at 15:39
  • There is no need to use a `static FloatToInt` for this -- and doing so makes this unnecessarily thread-unsafe. In `Convert(float value)` just `return new FloatToInt { f = value }.i;` Since `FloatToInt` is a struct, doing `new FloatToInt { }` doesn't allocate anything on the heap. – dbc Jul 30 '21 at 17:22
5

Use the BitConverter.ToSingle method:

int i = ...;
float f = BitConverter.ToSingle(BitConverter.GetBytes(i), 0);
Dmitry
  • 13,577
  • 6
  • 33
  • 47
2

The keyword float is an alias for the data type System.Single.

You can use the BitConverter.ToSingle to convert four bytes into a float.

Guffa
  • 666,277
  • 106
  • 705
  • 986
  • I've never heard about that alias, very interesting. – Hobbyist Dec 01 '14 at 21:42
  • Would this be the proper usage? ` byte ch1 = ReadByte(); byte ch2 = ReadByte(); byte ch3 = ReadByte(); byte ch4 = ReadByte(); return BitConverter.ToSingle(new byte[] { ch1, ch2, ch3, ch4 }, 0);` – Hobbyist Dec 01 '14 at 21:44
  • 2
    I wouldn't necessarily recommend this if (per the question) it is in network code, though; all those darned `byte[]`. I've added some alternatives separately. – Marc Gravell Dec 01 '14 at 22:20
2

Targeting .NET Core we are now finally able to simply use BitConverter.SingleToInt32Bits() and BitConverter.Int32BitsToSingle()!

D.R.
  • 18,900
  • 20
  • 82
  • 181
1

using the System.Runtime.CompilerServices.Unsafe nuget package

Unsafe.As<float, int>(ref value);

Will convert a float to an int

and

Unsafe.As<int, float>(ref value);

will convert an int to a float

Yair Halberstadt
  • 4,398
  • 24
  • 51
0

Since .NET Core 2.0 we've had a built-in API for this, BitConverter.Int32BitsToSingle:

float f = BitConverter.Int32BitsToSingle(i);
Drew Noakes
  • 284,599
  • 158
  • 653
  • 723
0

If you need this support on .NET Framework 4.0+ or .NET Standard 2.0, you can use J2N.BitConversion.Int32BitsToSingle(i) from the J2N NuGet Package.

Full disclosure: I am the primary maintainer of J2N.

NightOwl888
  • 53,678
  • 21
  • 130
  • 204