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
  • 98,240
  • 88
  • 296
  • 433
Hobbyist
  • 15,888
  • 9
  • 46
  • 98

8 Answers8

11

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
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 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
11

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
  • 104,963
  • 20
  • 228
  • 340
Aberro
  • 620
  • 6
  • 10
  • This is a great technique, thanks for this – NSJacob1 Jul 30 '21 at 15:39
  • 1
    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
  • Bitconverter doesn't create a buffer in .net core 7, at least. `public static unsafe int SingleToInt32Bits(float value) => *((int*)&value);` `public static unsafe float Int32BitsToSingle(int value) => *((float*)&value);` – Warty Jul 18 '23 at 09:19
  • @Warty It was about BitConverter.GetBytes(value). At the time there was no direct conversion methods, so you had to get bytes first. – Aberro Jul 27 '23 at 10:38
5

Use the BitConverter.ToSingle method:

int i = ...;
float f = BitConverter.ToSingle(BitConverter.GetBytes(i), 0);
Dmitry
  • 13,797
  • 6
  • 32
  • 48
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
  • 687,336
  • 108
  • 737
  • 1,005
  • 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.
  • 20,268
  • 21
  • 102
  • 205
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
  • 5,733
  • 28
  • 60
0

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

float f = BitConverter.Int32BitsToSingle(i);
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
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
  • 55,572
  • 24
  • 139
  • 212