gregseth
gregseth

Reputation: 13428

C#: Convert ushort to float

From a library I'm working with I recieve an array of ushort.

I want to convert them in an array of float: The first ushort represents the 16 MSB of the first float and the second ushort is the 16 LSB of the first float, and so on.

I tried with something like the following, but the value is cast as the value of the integer, not the raw bits:

ushort[] buffer = { 0xBF80, 0x0000 };
float f = (uint)buffer[0] << 16 | buffer[1];
// expected result  => f == -1            (0xBF800000)
// effective result => f == 3.21283686E+9 (0x4F3F8000)

Any suggestion?

Upvotes: 7

Views: 10084

Answers (6)

JDev129
JDev129

Reputation: 1

I know this threads super old but I had a similar problem nothing above fixed. I had to send a decimal value to a plc using modbus and my only option to write to the registers was a ushort array. Luckily the software on the plc could convert the ushort array back to the decimal, the issue was reading the data from the plc. Here is what I was able to get to work. ConvertTo takes the users input and creates the ushort array for the write and ConvertFrom takes the ushort array the program receives from the plc and converts it back to the float.

    private ushort[] ConvertTo(string value)
    {
        var bytes = BitConverter.GetBytes(float.Parse(value));
        return new ushort[] {
            BitConverter.ToUInt16(bytes, 0),
            BitConverter.ToUInt16(bytes, 2)
        };
    }

    private float ConvertFrom(ushort valueOne, ushort valueTwo)
    {
        byte[][] final = Array.ConvertAll(new ushort[] { valueOne, valueTwo }, delegate (ushort item) { return BitConverter.GetBytes(item); });
        return BitConverter.ToSingle(new byte[4] { final[0][0], final[0][1], final[1][0], final[1][1] }, 0);
    }

Upvotes: 0

Richard J. Ross III
Richard J. Ross III

Reputation: 55583

Use a C# union:

[System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]    
public struct FloatUShortUnion {
    [System.Runtime.InteropServices.FieldOffset(0)]
    float floatValue;

    [System.Runtime.InteropServices.FieldOffset(0)]
    ushort short1;

    [System.Runtime.InteropServices.FieldOffset(16)]
    ushort short2;
}

Upvotes: 1

Mike Dinescu
Mike Dinescu

Reputation: 55740

Have a look at the System.BitConverter class.

In particular, the ToSingle method which takes a sequence of bytes and converts them to a float.

 ushort[] buffer = {0xBF80, 0x0000};
 byte[] bytes = new byte[4];
 bytes[0] = (byte)(buffer[1] & 0xFF);
 bytes[1] = (byte)(buffer[1] >> 8);
 bytes[2] = (byte)(buffer[0] & 0xFF);
 bytes[3] = (byte)(buffer[0] >> 8);
 float value = BitConverter.ToSingle( bytes, 0 );

EDIT
In the example, I had reversed the MSB/LSB order.. Now it is correct

Upvotes: 12

Joachim Isaksson
Joachim Isaksson

Reputation: 180977

You should use the BitConverter class for that.

Convert the two ushorts to byte arrays with BitConverter.GetBytes(UInt16), concatenate the two arrays and use BitConverter.ToSingle(byte[] value,int startIndex) to convert the 4 bytes in the resulting array to a float.

Upvotes: 2

MNGwinn
MNGwinn

Reputation: 2394

I'd look at the System.BitConverter class. You can use BitConverter.GetBytes to turn your ushorts into byte arrays, then combine your byte arrays and use BitConverter to turn the byte array into a float.

Upvotes: 1

Matt Greer
Matt Greer

Reputation: 62037

You will need to use System.BitConverter, and convert the shorts to bytes.

http://msdn.microsoft.com/en-us/library/system.bitconverter.tosingle.aspx

Upvotes: 0

Related Questions