Results 1 to 16 of 16

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

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Dec 2023
    Posts
    17

    Resolved [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. #2
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,325

    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
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  3. #3
    Addicted Member -Franky-'s Avatar
    Join Date
    Dec 2022
    Location
    Bremen Germany
    Posts
    207

    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. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,247

    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. #5
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,746

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

    Quote Originally Posted by jmcilhinney View Post
    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)
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  6. #6

    Thread Starter
    Junior Member
    Join Date
    Dec 2023
    Posts
    17

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

    Quote Originally Posted by -Franky- View Post
    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. #7

    Thread Starter
    Junior Member
    Join Date
    Dec 2023
    Posts
    17

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

    Quote Originally Posted by dbasnett View Post
    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.
    Last edited by skyfox64; Dec 8th, 2023 at 04:23 AM.

  8. #8
    Addicted Member -Franky-'s Avatar
    Join Date
    Dec 2022
    Location
    Bremen Germany
    Posts
    207

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

    Quote Originally Posted by skyfox64 View Post
    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)
    Quote Originally Posted by skyfox64 View Post
    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.
    Last edited by -Franky-; Dec 7th, 2023 at 05:13 PM.

  9. #9

    Thread Starter
    Junior Member
    Join Date
    Dec 2023
    Posts
    17

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

    Quote Originally Posted by -Franky- View Post

    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. #10
    Addicted Member -Franky-'s Avatar
    Join Date
    Dec 2022
    Location
    Bremen Germany
    Posts
    207

    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.
    Last edited by -Franky-; Dec 8th, 2023 at 02:35 PM.

  11. #11
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,325

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

    Quote Originally Posted by -Franky- View Post
    Your Struct MySingle is incorrect. Check out my Struct MySingle from posting #3. There is a small but important difference.
    FieldOffset…..
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Dec 2023
    Posts
    17

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

    Quote Originally Posted by -Franky- View Post
    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. #13
    Addicted Member -Franky-'s Avatar
    Join Date
    Dec 2022
    Location
    Bremen Germany
    Posts
    207

    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. #14
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,247

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

    Quote Originally Posted by skyfox64 View Post
    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. #15
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  16. #16

    Thread Starter
    Junior Member
    Join Date
    Dec 2023
    Posts
    17

    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