How to read floating point numbers from a binary file

Post Reply
User avatar
MarkP
Posts: 71
Joined: Tue Apr 07, 2015 9:32 pm

How to read floating point numbers from a binary file

Post 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?

User avatar
Mr. Kibernetik
Site Admin
Posts: 4786
Joined: Mon Nov 19, 2012 10:16 pm
My devices: iPhone, iPad, MacBook
Location: Russia
Flag: Russia

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

Post 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

User avatar
Dutchman
Posts: 851
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

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

Post 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.

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

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

Post 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 3588 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.😁

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

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

Post 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

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

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

Post 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

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

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

Post 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 3551 times

User avatar
MarkP
Posts: 71
Joined: Tue Apr 07, 2015 9:32 pm

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

Post by MarkP »

Thank you so much, Henko -- a true "codemeister"!

Post Reply