# Thread: [RESOLVED] Convert two int16 numbers to resolve the 32bit Float value represented by them. How?

1. ## [RESOLVED] Convert two int16 numbers to resolve the 32bit Float value represented by them. How?

I have two 16bit integers (HighWord, LowWord) that represents an IEEE 32bit floating point value.
How do I combine these and resolve the floating-point value represented by them? All the conversion functions that I have come across only takes a single argument for the conversion. Can someone point me in the right direction?

Thanks.

2. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

In Pascal (or C) i'd use a UNION-Record/Struct, but apparently VB.NET doesn't support that.

Quick and dirty idea:
Put your two 16-Bit integers into a record/Structure (correct order of Fields!! --> LE vs BE).
Create a Record/Structure with a single 32-Bit double/Float-Member,
CopyMemory the bytes from the Integer-Struct to the Double-Struct

3. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Maybe the following will work.
Code:
```Imports System.Runtime.InteropServices

Public Class Form1

<StructLayout(LayoutKind.Explicit, Size:=4)>
Private Structure MySingle
<FieldOffset(0)> Dim HiLo As Single
<FieldOffset(0)> Dim HiWord As Short
<FieldOffset(2)> Dim LoWord As Short
End Structure

' or

'<StructLayout(LayoutKind.Explicit, Size:=4)>
'Private Structure MySingle
'    <FieldOffset(0)> Dim HiLo As Single
'    <FieldOffset(0)> Dim LoWord As Short
'    <FieldOffset(2)> Dim HiWord As Short
'End Structure

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim mSingle As New MySingle With {
.LoWord = 16320,
.HiWord = 0
}
Debug.Print(mSingle.HiLo.ToString) ' -> 1.5
End Sub
End Class```

4. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

I wonder whether the BitConverter class could do it. It can get a Byte array from a Short and it can get a Single from a Byte array, so you may be able to do the former twice, combine the results and then do the latter.

5. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by jmcilhinney
I wonder whether the BitConverter class could do it. It can get a Byte array from a Short and it can get a Single from a Byte array, so you may be able to do the former twice, combine the results and then do the latter.
Like this maybe,

Code:
```        Dim sh1 As Int16 = Int16.MaxValue \ 2
Dim sh2 As Int16 = 12
Dim int As Int32 = (sh2 << 16) Or sh1
Dim sng As Single = BitConverter.ToSingle(BitConverter.GetBytes(int), 0)```

6. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by -Franky-
Maybe the following will work.
Code:
```    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim mSingle As New MySingle With {.LoWord = 16320,  .HiWord = 0}
Debug.Print(mSingle.HiLo.ToString) ' -> 1.5
End Sub```
Hi Franky,

Thanks for the reply.
Unfortunately, this does not do it. it simply assigns values to Hi and Lo shorts. I don't see any logic for combining the two in to HiLo.

Cheers.

7. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by dbasnett
Like this maybe,

Code:
```        Dim sh1 As Int16 = Int16.MaxValue \ 2
Dim sh2 As Int16 = 12
Dim int As Int32 = (sh2 << 16) Or sh1
Dim variable As Single = BitConverter.ToSingle(BitConverter.GetBytes(int), 0)```
Thanks dbasnett.

This gets close but the conversion is still off. Slight modification needed to be made to get this to work. You have to create another int32 variable and assign it the value of sh2 before you can perform the right shift operation. I believe the data type has to be the same for a bit shift operation. I am using vb2017 and it does not allow me to right shift bits from a short over to an int32 variable. It does not generate an error; it simply doesn't carry out the bit shift operation.

Code:
```
Dim sh1 As Int16 = 10 ' Low Word
Dim sh2 As Int16 = 16673 ' High Word
Dim int0 As Int32 = sh2 ' Create a new integer variable to allow right shift operator to work
Dim int As Int32 = 0
int = (int0 << 16) Or sh1 ' Perform the right shift with the high word and Or with the low word
Dim sng As Single = BitConverter.ToSingle(BitConverter.GetBytes(int), 0)
MsgBox(sng)```
On the above modified example based on the code you provided ...

Low Word = 10
High Word = 16673

Should yield a float value of 10.123, but the code generated result is 10.06251. Which is incorrect. Not sure how to fix that. This logic fails if either one of or both hi/lo words have a negative value.

For example, for a floating-point value of -10.123
Low Word = -10
High Word = -16095

Code above says this is not a number (NaN) which is incorrect.

Thanks again for the help.

Cheers.

EDIT:

Just found out Low word values given above by me for float value of 10.123 is incorrect.

Instead of

Low Word = 10
High Word = 16673

it should have been...

Low Word = -2097
High Word = 16673

I found this thanks to Franky's code below. Thank you, Franky. I posted earlier values based on what my controller was sending via a MODBUS interface. It so happens, that this controller's hardware vendor upgraded their firmware which corrupted the Hi/Low word generation. I tested with an earlier version of their firmware and found out it was previously working correctly and matched the hi/Lo words obtained from Franky's code below. Just putting it out here so I don't mislead anyone with incorrect short register values for a float value of 10.123. Posted values above for -10.123 are also incorrect.

Cheers.

8. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by skyfox64
Low Word = 10
High Word = 16673
Should yield a float value of 10.123...
Code:
```        Dim SingleVal As Single = 10.123
Dim BytesVal As Byte() = BitConverter.GetBytes(SingleVal)
Dim LoWord As Short = BitConverter.ToInt16(BytesVal, 0)
Dim HiWord As Short = BitConverter.ToInt16(BytesVal, 2)

Debug.Print("LoWord: " & LoWord.ToString)
Debug.Print("HiWord: " & HiWord.ToString)```
Originally Posted by skyfox64
Unfortunately, this does not do it. it simply assigns values to Hi and Lo shorts. I don't see any logic for combining the two in to HiLo.
It does exactly what Zvoni describes: In Pascal (or C) i'd use a UNION-Record/Struct. You just write in two shorts and read the single or vice versa.

9. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by -Franky-

It does exactly what Zvoni describes: In Pascal (or C) i'd use a UNION-Record/Struct. You just write in two shorts and read the single or vice versa.

Code:
```    Private Structure MySingle
Dim HiLo As Single
Dim LoWord As Short
Dim HiWord As Short
End Structure

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim mSingle As New MySingle With {.LoWord = 16320,.HiWord = 0}
Debug.Print(mSingle.HiLo.ToString) ' -> 1.5
End Sub```
Hi Franky,

Above code returns "0" not 1.5. What am I doing wrong? I don't see where "HiLo" gets assigned a value. I.e. logic for where the two shorts get combined in to a single.

Cheers.

10. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Your Struct MySingle is incorrect. Check out my Struct MySingle from posting #3. There is a small but important difference.

11. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by -Franky-
Your Struct MySingle is incorrect. Check out my Struct MySingle from posting #3. There is a small but important difference.
FieldOffsetâ€¦..

12. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by -Franky-
Your Struct MySingle is incorrect. Check out my Struct MySingle from posting #3. There is a small but important difference.
Franky, Zvoni,

Thank you. That did the trick. This is the first time I had to use what looked like xml code tags before a declaration statement and a dim statement in VB. If you haven't guessed already, I am not a VB programmer by trade. Pardon me for being stupid. I still don't understand the mechanism behind this structure. i.e. How HiLo gets its value based on the two shorts declared and assigned within the structure. In other words, I haven't figured out what a structure is or how it works.

Cheers.

13. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

I'll try to explain it as simply as possible.

In your struct, without FieldOffset and with an align of 4, the data is stored as follows.
|0 1 2 3|4 5 6 7|8 9 10 11|
0-3 = Float (4Byte)|4-5 = Int16 (2Byte)|8-9 = Int16 (2Byte)

In my Struct, the data with FieldOffset is in memory as follows.
|0 1 2 3|
0-3 = Float (4Byte)|0-1 = Int16 (2Byte)|2-3 = Int16 (2Byte)

14. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Originally Posted by skyfox64
This is the first time I had to use what looked like xml code tags before a declaration statement and a dim statement in VB. If you haven't guessed already, I am not a VB programmer by trade. Pardon me for being stupid. I still don't understand the mechanism behind this structure. i.e. How HiLo gets its value based on the two shorts declared and assigned within the structure. In other words, I haven't figured out what a structure is or how it works.
Those are attributes. They are metadata about a type or member. They tell the system how it should be used. The structure occupies a memory location and the field offset is how many bytes from the beginning of that location each field is stored. In this case, you have a 4-byte structure with a Single stored from an offset of zero and two Shorts stored from offsets of zero and 2. That means that the Short values are literally occupying the hiword and loword of the Single. Any change made to one of the Shorts will inherently affect the Single occupying the same memory and vice versa.

15. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

Sorry I'm late to the game, I don't visit here very often any more, but I've often had to pack and unpack date of various types from packets and I usually use two functions to unpack values, Buffer.BlockCopy and BitConverter.ToSingle (in this case).
A quick example, which expects the two 16-bit integers (Hi, Lo) to be passed in an array and returns the Single they represent:
Code:
```Private Function TwoWords_to_IEEE32(Words() as UInt16) As Single
Dim b(3) as Byte 'byte array to hold the two words for conversion

Buffer.BlockCopy(Words, 0, b, 0, 4) 'copy 4 bytes from offset 0 of Words to offset 0 of b
Return BitConverter.ToSingle(b, 0)
End Function```
To go the other way, the core of the conversion would be
Code:
```  'assuming variable s is a parameter of type Single that was passed to the function
Dim w(1) As Int16

b = BitConverter.GetBytes(s)
Buffer.BlockCopy(b, 0, w, 0, 4)```
If you needed to swap the word oder, you could change the offset value and the number of bytes copied, i.e.
Code:
```  Buffer.BlockCopy(b, 0, w, 2, 2)  'Copy the lower 2 bytes of b into the upper 2 bytes of w, i.e. to w(1)
Buffer.BlockCopy(b, 2, w, 0, 2)  'Copy the upper 2 bytes of b into the lower 2 bytes of w, i.e. to w(0)```
I like packing and unpacking packets this way for two reasons over mapping a structure.
First, it is easier to handle endianness when you have to go between big endian and little endian representations.
Second, it is easier to add conversions and test them dynamically while paused in the debugger as you can code the conversion, test the code, field by field without having to recompile.

Caveat. I typed this reply on a Mac so don't have a version of Visual Studio installed so if there are any typo's above, hopefully you can easily fix them.

16. ## Re: Convert two int16 numbers to resolve the 32bit Float value represented by them. H

-franky-, Zvoni, jmcilhinney, passel,

Thank you all for your help on this.

HAPPY NEW YEAR!

Cheers.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

Click Here to Expand Forum to Full Width