IEE754 floating point

4 views
Skip to first unread message

Eur van Andel

unread,
Nov 5, 2019, 1:20:33 PM11/5/19
to jal...@googlegroups.com
Hi All


I have a sensor here that spits out four bytes in IEEE 754 floating point format. I remembered Kyle muttering that he didn’t use this particulate floating point format and with zero examples of float variables in the sample files, I wrote my own procedures. Both work. Both have obvious errors, which I don’t understand. 

Question:

Is input as 1 dword preferred over 45 bytes?

Sources: 


Problems:

Floating point mantissa is a number between 1 and 2, where the 1 before the decimal point is conveniently removed. The bits store the 1/2, 1/4, 1/8.. values. 
I needed to go to decimal, so I used 5_000_000 and shifted that to the right (2_500_000, 1_250_000, etc) which should add up to 1e7 max if all mantissa bits are 1. 
I forgot the 1e8 😀
In my opinion 1.5xxx * 2^y is very different from 0.5xxx * 2^y, but the result is correct?
Also, when divided by 1e7, this doesn’t work? For some reason my value is 10x too small. Easy fix. 
I also used the 23rd bit of the mantissa, counting from 1. Jal counts from 0, so this should be bit 22. Yet, it works. 

For the dword variant I corrected the 23 to 22 (the mantissa formally needs no mask from the fp input value, since I only use one bit) but this gave a result that was 4 times too large. Easy fix, but even less understandable. 

Any ideas about the sample that I should make for this? Are there typical IEEE 754 numbers that I should use as an example? I am also a bit worried about the limited exponent range in my code. For larger exponents I could shift leftward one bit and a time and catch the overflow in a separate byte, so I can cover the full dword range. 

I’m also not sure about the way how the conversion works the other way. After all, 1/2 * 2^1, 1/4 * 2^2 and 1/8 * 2^3 are all 1. There must be a preferred format.


-- -------------------------------------------------------------------
-- IEE 754 floating point conversion: 1 sign bit, 8 exponent bits, 23 mantissa bits
-- max 4 digits after decimal point
-- Original: Eur van Andel
-- -------------------------------------------------------------------
function ieee754_to_sdword(byte in fp3, byte in fp2, byte in fp1, byte in fp0, byte in digits) return sdword is
   var bit sign at fp3:7            -- 1 bit sign
   var byte exponent                -- 8 bits exponent
   var dword mantissa               -- 23 bits mantissa, 32 bits here
   var bit sig_bit at mantissa:23   -- most significant bit
   var dword value = 0
   var dword fraction = 5_000_000         -- 7 digits
   exponent = (fp3 << 1) + (fp2 >> 7)
   mantissa = dword(fp2 & 0b0111_1111) 
   mantissa = mantissa << 15              -- only 7 bits, 8th is for exponent
   mantissa = mantissa + (word(fp1) << 8) + fp0
   
   exponent = exponent - 127        -- exponent bias, fake sbyte
      
   for 22 loop 
      if sig_bit then 
         value = value + fraction
      end if 
      mantissa = mantissa << 1
      fraction = fraction >> 1      -- add 1/2, 1/4, etc of 10^7
   end loop
   
   value = value << exponent  -- exponent max 8 here, not that much
   
   if digits == 0 then 
      value = value / 1_000_000  -- should be 10^7? this works, dunno why
   elsif digits == 1 then 
      value = value / 100_000
   elsif digits == 2 then 
      value = value / 10_000
   elsif digits == 3 then 
      value = value / 1_000
   elsif digits == 4 then 
      value = value / 100
   end if                     -- more digits too slow
      
   if sign then 
      return - sdword(value)
   else 
      return sdword(value)
   end if
end function
   

-- -------------------------------------------------------------------
-- IEE 754 floating point conversion: 1 sign bit, 8 exponent bits, 23 mantissa bits
-- max 4 digits after decimal point
-- Original: Eur van Andel
-- -------------------------------------------------------------------
function ieee754_to_sdword2(dword in fp, byte in digits) return sdword is
   var bit sign at fp:31                                 -- 1 bit sign
   var byte exponent  = byte((fp & 0x7F_80_00_00) >> 23) -- 8 bits exponent
   var dword mantissa =       fp & 0x00_7F_FF_FF         -- 23 bits mantissa
   var bit sig_bit at mantissa:22   -- most significant bit
   var dword value = 0
   var dword fraction = 5_000_000         -- 7 digits
   
   exponent = exponent - 127        -- exponent bias, fake sbyte
      
   for 22 loop 
      if sig_bit then 
         value = value + fraction
      end if 
      mantissa = mantissa << 1
      fraction = fraction >> 1      -- add 1/2, 1/4, etc of 10^7
   end loop
    
   if exponent > 2 then             
      exponent = exponent -2     -- dafuq?
      value = value << exponent  -- exponent max 8 here, not that much
   else 
      value = value << exponent 
      value = value >> 2
   end if
   
   if digits == 0 then 
      value = value / 1_000_000  -- should be 10^7? this works, dunno why
   elsif digits == 1 then 
      value = value / 100_000
   elsif digits == 2 then 
      value = value / 10_000
   elsif digits == 3 then 
      value = value / 1_000
   elsif digits == 4 then 
      value = value / 100
   end if                     -- more digits too slow
      
   if sign then 
      return - sdword(value)
   else 
      return sdword(value)
   end if
end function

---
Fiwihex B.V. Wierdensestraat 74, NL7604BK Almelo, Netherlands
tel+31-653-286573




Reply all
Reply to author
Forward
0 new messages