Page 1 of 1

How to read floating point numbers from a binary file

Posted: Tue Apr 09, 2019 7:42 pm
by MarkP
SmartBasic has the FILE N$ READ function to read bytes from a binary file. Unfortunately, because there is no facility within sB to poke or peek values into variables, I am at a total loss on how to read 32-bit IEEE floating point values from a binary file.

Specifically, I'm trying to read a sequence of 32-bit floats (little-endian) from a binary STL file.

Does anyone have some advice on this?

Re: How to read floating point numbers from a binary file

Posted: Tue Apr 09, 2019 11:10 pm
by Mr. Kibernetik
I think that conversion algorithm will be needed.
Maybe this site can be of some help: https://www.h-schmidt.net/FloatConverter/IEEE754.html

Re: How to read floating point numbers from a binary file

Posted: Wed Apr 10, 2019 7:52 am
by Dutchman
That is not really easy :lol:
The value of a IEEE-754 number is computed as:

sign 2exponent mantissa

The sign is stored in bit 32. The exponent can be computed from bits 24-31 by subtracting 127. The mantissa (also known as significand or fraction) is stored in bits 1-23. An invisible leading bit (i.e. it is not actually stored) with value 1.0 is placed in front, then bit 23 has a value of 1/2, bit 22 has value 1/4 etc. As a result, the mantissa has a value between 1.0 and 2. If the exponent reaches -127 (binary 00000000), the leading 1 is no longer used to enable gradual underflow.

Re: How to read floating point numbers from a binary file

Posted: Wed Apr 10, 2019 8:37 am
by Henko
Hi Mark,
Indeed it is not easy, but we will give it a try. Dutchman already indicated the structure of the 32 bit floatingpoint presentation. So the first step is to convert any group of 4 bytes read from a file using the FILE f$ READ a,b,c,d command into a string which contains the binary equivalent of those 4 bytes:

Code: Select all

dim a(4)
read a(0),a(1),a(2),a(3)
data 129,17,6,1
print a(0);a(1);a(2);a(3)
print bin32$(a)
end

' convert 4 bytes to a 32 long 'binary' string
'
def bin32$(byt())
ret$="" ! ob=option_base()
for i=ob to 4+ob-1 ! ret$&=dec2bin8$(byt(i)) ! next i
return ret$
end def

' convert an unsigned decimal number 0 - 255 to 8-bit binary string
'
def dec2bin8$(n)
b$=""
do ! r=n%2 ! n=floor(n/2) ! b$&=chr$(r+48) ! until n=0
while len(b$)<8 ! b$&="0" ! end while
return reverse$(b$)
end def
A9F2700C-485F-47F6-AB8C-DD6355BAFABE.png
A9F2700C-485F-47F6-AB8C-DD6355BAFABE.png (272.29 KiB) Viewed 3505 times

The following step is of course interpretation of the three parts of that binary string as indicated by Dutchman and convert those to the number in the desired format.

If you don't manage to do that, let me know and i will give it a try.😁

Re: How to read floating point numbers from a binary file

Posted: Wed Apr 10, 2019 2:25 pm
by Henko
Well, it wasn't that difficult after all 😉

Code: Select all

dim a(4)
read a(0),a(1),a(2),a(3) ! data 129,17,6,1
print bytes2float(a)
end

' convert 4 bytes internal IEEE 754 representation to float number
' array a() contains 4 bytes
' option base independent
' 
def bytes2float(a())
c$=bin32$(a)
s=val(left$(c$,1))
e=bin2dec(mid$(c$,option_base()+1,8))-127
m=bin2invdec(right$(c$,23))
return (-1)^s*(1+m)*2^e
end def

def bin32$(byt())
ret$="" ! ob=option_base()
for i=ob to 4+ob-1 ! ret$&=dec2bin8$(byt(i)) ! next i
return ret$
end def

def dec2bin8$(n)
b$=""
do ! b$&=chr$(n%2+48) ! n=floor(n/2) ! ! until n=0
while len(b$)<8 ! b$&="0" ! end while
return reverse$(b$)
end def

def bin2dec(b$)
ob=option_base() ! d=0 ! pow=1 ! b$=reverse$(b$)
for i=ob to len(b$)+ob-1
  if mid$(b$,i,1)="1" then d+=pow ! pow*=2
  next i
return d
end def

def bin2invdec(b$)
ob=option_base() ! d=0 ! pow=1
for i=ob to len(b$)+ob-1
  pow/=2 ! if mid$(b$,i,1)="1" then d+=pow
  next i
return d
end def

Re: How to read floating point numbers from a binary file

Posted: Sat Apr 13, 2019 7:08 am
by Henko
Here is the conversion function in compact form.
Without comments really a "black box". Also for me after one week 🤔

Code: Select all

dim a(4)
read a(0),a(1),a(2),a(3) ! data 129,17,6,1
print bytes2float(a)
end

' convert 4 bytes internal IEEE 754 representation to float number
' array a() contains 4 bytes
' option base independent
' 
def bytes2float(a())
c$="" ! ob=option_base()
for i=ob to 4+ob-1
  b$="" ! n=a(i)
  do ! b$&=chr$(n%2+48) ! n=floor(n/2) ! until n=0
  while len(b$)<8 ! b$&="0" ! end while
  c$&=reverse$(b$)
  next i
s=val(left$(c$,1))
d=0 ! pow=1! e$=reverse$(mid$(c$,ob+1,8))
for i=ob to len(e$)+ob-1
  if mid$(e$,i,1)="1" then d+=pow ! pow*=2
  next i
e=d-127
m=0 ! pow=1 ! m$=right$(c$,23)
for i=ob to len(m$)+ob-1
  pow/=2 ! if mid$(m$,i,1)="1" then m+=pow
  next i
return (-1)^s*(1+m)*2^e
end def

Re: How to read floating point numbers from a binary file

Posted: Tue Apr 16, 2019 10:11 am
by Henko
A conversion function from A into B should be accompanied whith its nephew from B to A.
Here is the function which converts a float number to the 4 bytes IEEE754 internal representation.

Code: Select all

dim a(4)
x=-0.00001234567
float2ieee(x,a)
print x,ieee2float(a)
end

def float2ieee(x,bytes())
ob=option_base() ! option base 1
dim v(32)
if x<0 then v(1)=1 else v(1)=0
m=abs(x) ! exp=127
while m>=2 ! exp+=1 ! m/=2 ! end while
while m<=1 ! exp-=1 ! m*=2 ! end while
m-=1
pow=128
for i=2 to 9
  v(i)=0 ! if exp>=pow then ! v(i)=1 ! exp-=pow ! end if
  pow/=2
  next i
pow=1
for i=10 to 32
  pow/=2
  v(i)=0 ! if m>=pow then ! v(i)=1 ! m-=pow ! end if
  next i
for k=1 to 4
  pow=128 ! s=1+8*(k-1) ! b=0
  for i=s to s+7
    if v(i) then b+=pow ! pow/=2
    next i
  bytes(k)=b
  next k
option base ob
end def

' convert 4 bytes internal IEEE 754 representation to float number
' array a() contains 4 bytes
' option base independent
' 
def ieee2float(a())
c$="" ! ob=option_base()
for i=ob to 3+ob
  b$="" ! n=a(i)
  do ! b$&=chr$(n%2+48) ! n=floor(n/2) ! until n=0
  while len(b$)<8 ! b$&="0" ! end while
  c$&=reverse$(b$)
  next i
s=val(left$(c$,1))
e=0 ! pow=1! e$=reverse$(mid$(c$,ob+1,8))
for i=ob to 7+ob
  if mid$(e$,i,1)="1" then e+=pow ! pow*=2
  next i
e-=127
m=0 ! pow=1 ! m$=right$(c$,23)
for i=ob to 22+ob
  pow/=2 ! if mid$(m$,i,1)="1" then m+=pow
  next i
return (-1)^s*(1+m)*2^e
end def
FA115133-C77C-42DD-BDF2-77AACB8EAEA4.png
FA115133-C77C-42DD-BDF2-77AACB8EAEA4.png (271.05 KiB) Viewed 3468 times

Re: How to read floating point numbers from a binary file

Posted: Wed Apr 17, 2019 3:47 pm
by MarkP
Thank you so much, Henko -- a true "codemeister"!