Two byte floating point number.

A long time ago i had to deal with 2 byte floating point numbers in VB6.
Now I have to convert my old project to Xojo.

Example:
2bytes hex = desimal value

&h1400 = 1
&hB001 = 1
&h1C00 = -1
&hB801 = -1
&h7640 = 100
&hB064 = 100
&h7634= 99.2
&h6544= 42.1

I have my VB6 code from way back in time casting long to a single loosing bits and back.
How to make this work in Xojo ?

[code]Public Type Sng
dta As Single
End Type

Public Type Lng
dta As Long
End Type

Public Function IEEE_To_Normal(ByVal Ieee As String) As Single
Dim vLng As Lng
Dim vSng As Sng
vLng.dta = Ieee
LSet vSng = vLng
IEEE_To_Normal = vSng.dta
End Function

Public Function Normal_To_Ieee(ByVal Normal As Single) As String
Dim vLng As Lng
Dim vSng As Sng
vSng.dta = Normal
LSet vLng = vSng
Normal_To_Ieee = Hex$(vLng.dta)
End Function[/code]

The explanation using low level exponet and mantissa calculation:
The 16 bits string is characterized by three components,
an exponent, a sign and a significant. Its numerical value is the signed product of its significant and
two raised to the power of its exponent.

2 Bytes Floating Point Format where:
e 4 bits exponent. Any integer between 0 and 15
s 1 bit sign (0 = positive, 1 = negative)
f 11 bits fractional significant with an implied binary point
and the format: 0.b0b1…b10
The numerical value of a floating point string can be calculated as:
Numerical Value = (-1)s 2e (0.b0b1…b10)
The numerical value of the nth bit (bn) in the significant field (n from 0 to 10) is:
Significant Value(bn) = 2-(n + 1)
A number is zero when all bits of the fractional significant are 0.

[quote=153248:@Kato Gangstad]A long time ago i had to deal with 2 byte floating point numbers in VB6.
Now I have to convert my old project to Xojo.

Example:
2bytes hex = desimal value

&h1400 = 1
&hB001 = 1
&h1C00 = -1
&hB801 = -1
&h7640 = 100
&hB064 = 100
&h7634= 99.2
&h6544= 42.1

I have my VB6 code from way back in time casting long to a single loosing bits and back.
How to make this work in Xojo ?

[code]Public Type Sng
dta As Single
End Type

Public Type Lng
dta As Long
End Type

Public Function IEEE_To_Normal(ByVal Ieee As String) As Single
Dim vLng As Lng
Dim vSng As Sng
vLng.dta = Ieee
LSet vSng = vLng
IEEE_To_Normal = vSng.dta
End Function

Public Function Normal_To_Ieee(ByVal Normal As Single) As String
Dim vLng As Lng
Dim vSng As Sng
vSng.dta = Normal
LSet vLng = vSng
Normal_To_Ieee = Hex$(vLng.dta)
End Function[/code]

The explanation using low level exponet and mantissa calculation:
The 16 bits string is characterized by three components,
an exponent, a sign and a significant. Its numerical value is the signed product of its significant and
two raised to the power of its exponent.

2 Bytes Floating Point Format where:
e 4 bits exponent. Any integer between 0 and 15
s 1 bit sign (0 = positive, 1 = negative)
f 11 bits fractional significant with an implied binary point
and the format: 0.b0b1…b10
The numerical value of a floating point string can be calculated as:
Numerical Value = (-1)s 2e (0.b0b1…b10)
The numerical value of the nth bit (bn) in the significant field (n from 0 to 10) is:
Significant Value(bn) = 2-(n + 1)
A number is zero when all bits of the fractional significant are 0.[/quote]

Use a single ?

Singel is 4 bytes…

VB’s single was 16 bits ?

EDIT : VB’s Single is 32 bits as well

No, but when I did the conversion like that I shifted the lower bits not needed.
I will use single in Xojo, but when I read and write to my device I have to convert it to “half” format

I believe the number format is called “half”

EDIT:
Shifted is wrong…

Interesting as the code you posted just uses at least 32 bit types(single is 32 bit and LONG is 64) so I’d expect that portion of it to just port directly without having to do much

I’m not sure where you do the shifting but its not that code

LSet() in its code which has been used with two user defined data types (Type), to assign data from one type to another.

By writing the decimal value to a long and “Lset” it to a single we loose the precision. (half…)

Could I use “CType” for this ?

My VB is SO rusty I honestly dont know
I’d probably have to run some code to see this in action to follow whats going on because my VB is so rusty

Data type “Single” is same in VB6 and Xojo. The data type “Long” in VB6 is same as Xojo “Int32”. The rest of the port from VB to Xojo may have to be tried and tested step by step.

In VB6 the following hex values are obtained when “Normal_To_Ieee” is called with indicated decimal values. It is not clear how the two byte hex values are obtained from the provided VB code.

Decimal 1 = Hex 3F800000 Decimal 100 = Hex 42C80000 Decimal 99.2 = Hex 42C66666

Hmm, thanks for testing.
This is the same results I got from my Xojo tries now.
I guess I have to Install VB6 on a computer and open my old projects to figure out how I did it…

I have the right code…
Found my first attemt to convert 2 bytes to analog doing the math.
And the replacemt function.

Old Working Code:

Private Function AnalogValue(ByVal Stri As String) As Double ' Old type.. If Stri = "" Then Exit Function Dim E(3), s, M(11) As Boolean word = Mid(Stri, 2, 4) word = Bytt(word) Byte1 = Mid(word, 1, 1) Byte2 = Mid(word, 2, 1) Byte3 = Mid(word, 3, 1) Byte4 = Mid(word, 4, 1) Byte1 = Val("&h" & Byte1) Byte2 = Val("&h" & Byte2) Byte3 = Val("&h" & Byte3) Byte4 = Val("&h" & Byte4) E(3) = Binn(Byte1, 3) E(2) = Binn(Byte1, 2) E(1) = Binn(Byte1, 1) E(0) = Binn(Byte1, 0) s = Binn(Byte2, 3) M(10) = Binn(Byte2, 2) M(9) = Binn(Byte2, 1) M(8) = Binn(Byte2, 0) M(7) = Binn(Byte3, 3) M(6) = Binn(Byte3, 2) M(5) = Binn(Byte3, 1) M(4) = Binn(Byte3, 0) M(3) = Binn(Byte4, 3) M(2) = Binn(Byte4, 2) M(1) = Binn(Byte4, 1) M(0) = Binn(Byte4, 0) Exponent = Byte1 For t = 0 To 10 If M(t) = True Then Mantissa = Mantissa + 2 ^ (Exponent - 11 + t) Next t AnalogValue = Mantissa If s Then AnalogValue = AnalogValue * -1 AnalogValue = Round(AnalogValue, 1) End Function

It’s easy to convert this code to Xojo.
But I also need a function that does the opposite, (from analog value to 2 byte)

Code that replaced this one:

Private Function Analog(ByVal ST As String) As Double 'new type... Dim word As String If ST = "" Then Exit Function word = Mid(ST, 2, 4) Analog = IEEE_To_Normal("&h" & word & "0000") End Function

Here’s a conversion from Single to Half

Function Float32ToFloat16(d as single) As Int16
  dim mb1 as new MemoryBlock(4)
  dim mb2 as new MemoryBlock(2)
  dim result as Int16
  mb1.LittleEndian= false
  mb2.LittleEndian= false
  
  mb1.SingleValue(0)= d
  
  // sign bit
  mb2.byte(0) = mb1.byte(0) AND &h80
  
  // exponent
  dim exp as integer
  exp = mb1.Int16Value(0) AND &h7f80     // bits 2-9 of 16
  exp = bitwise.ShiftRight(exp, 7)
  if exp<> 0 then
    exp= exp - 127  // bias for single
    exp = exp mod 16
    exp= exp + 15   //bias for half
    exp = exp AND &h1F    // only need 5 significant bits
    exp = bitwise.ShiftLeft(exp, 2)   // bits 2-6 of 8
    mb2.byte(0) = mb2.byte(0) OR exp
  end
  
  // mantissa
  dim man as integer
  man = mb1.Int32Value(0) AND &h7FFFFF
  man = ShiftRight(man, 13)    // only need first 10 bits
  mb2.Int16Value(0) = mb2.Int16Value(0) OR man
  
  result = mb2.Int16Value(0)
  return result
  
End Function

I think I could also add something to my plugins in case someone needs it in future :slight_smile:

Thanks Tim I’ll give it a try.
Do you also have a function to convert the other way ?

Christian that would be great !
See you in Austin?

Already uploaded new plugin 14.5pr4 with that feature.

And I got my ticket for Austin already.
Just waiting for getting credit card company to do a double mile promotion before ordering flight ticket :slight_smile:

You just sold a license !
I was going to purchase the Mbs Curl plug in anyway.
Say hallo to you wife from me and buy her someting nice for X-mas

Reversing it should be simple. I just ran out of time. I did test that code against the values in the Wikipedia page.

Sorry to say it guys…
I can’t use eithers code…

The format i’m dealing with have 4 bits exponent and 11 bits mantissa…
Not 5 and 10 like the standard

I wondered why your results were different. I can tweak my code if you want to try it.