ruby - Converting a floating point to its corresponding bit-segments -


given ruby float value, e.g.,

f = 12.125 

i'd wind 3-element array containing floating-point number's sign (1 bit), exponent (11 bits), , fraction (52 bits). (ruby's floats ieee 754 double-precision 64-bit representation.)

what's best way that? bit-level manipulation doesn't seem ruby's strong point.

note want bits, not numerical values correspond to. instance, getting [0, -127, 1] floating-point value of 1.0 not i'm after -- want actual bits in string form or equivalent representation, ["0", "0ff", "000 0000 0000"].

the bit data can exposed via arrays pack float doesn't provide functions internally.

str = [12.125].pack('d').bytes.reverse.map{|n| "%08b" %n }.join => "0100000000101000010000000000000000000000000000000000000000000000"  [ str[0], str[1..11], str[12..63] ] => ["0", "10000000010", "1000010000000000000000000000000000000000000000000000"] 

this bit 'around houses' pull out string representation. i'm sure there more efficient way pull data original bytes...


edit bit level manipulation tweaked interest had poke around. use operations in ruby need have integer float requires more unpacking convert 64 bit int. big endian/ieee754 documented representation trivial. little endian representation i'm not sure about. it's little odd, not on complete byte boundaries 11 bit exponent , 52 bit mantissa. it's becomes fiddly pull bits out , swap them resembles little endian, , not sure if it's right haven't seen reference layout. 64 bit value little endian, i'm not sure how applies components of 64bit value until store them somewhere else, 16bit int mantissa.

as example 11 bit value little > big, kind of thing doing shift significant byte left 3 front, or least significant 3 bits.

v = 0x4f2 ((v & 0xff) << 3) | ( v >> 8 )) 

here anyway, of use.

class float   float::little_endian = [1.0].pack("e") == [1.0].pack("d")    # returns sign, exponent , mantissa integers   def ieee745_binary64     # build big end int representation can use bit operations     tb = [self].pack('d').unpack('q>').first      # check     if float::little_endian       ieee745_binary64_little_endian tb     else       ieee745_binary64_big_endian tb     end   end    # force little end calc   def ieee745_binary64_little     ieee745_binary64_little_endian [self].pack('e').unpack('q>').first   end    # force big end calc   def ieee745_binary64_big     ieee745_binary64_big_endian [self].pack('g').unpack('q>').first   end    # little   def ieee745_binary64_little_endian big_end_int     #puts "big #{big_end_int.to_s(2)}"     sign     = ( big_end_int & 0x80   ) >> 7      exp_a    = ( big_end_int & 0x7f   ) << 1   # last 7 bits, make more significant     exp_b    = ( big_end_int & 0x8000 ) >> 15  # 9th bit, fill sign gap     exp_c    = ( big_end_int & 0x7000 ) >> 4   # 10-12th bit stick on front     exponent = exp_a | exp_b | exp_c      mant_a   = ( big_end_int & 0xffffffffffff0000 ) >> 12 # f000 taken above     mant_b   = ( big_end_int & 0x0000000000000f00 ) >> 8  #  f00 left on     mantissa = mant_a | mant_b      [ sign, exponent, mantissa ]   end    # big   def ieee745_binary64_big_endian big_end_int     sign     = ( big_end_int & 0x8000000000000000 ) >> 63     exponent = ( big_end_int & 0x7ff0000000000000 ) >> 52     mantissa = ( big_end_int & 0x000fffffffffffff ) >> 0      [ sign, exponent, mantissa ]   end end 

and testing...

def printer val, vals   printf "%-15s   sign|%01b|\n",            val,     vals[0]   printf "  hex e|%3x|         m|%013x|\n", vals[1], vals[2]   printf "  bin e|%011b| m|%052b|\n\n",     vals[1], vals[2] end  floats = [ 12.125, -12.125, 1.0/3, -1.0/3, 1.0, -1.0, 1.131313131313, -1.131313131313 ]  floats.each |v|   printer v, v.ieee745_binary64   printer v, v.ieee745_binary64_big end 

til brain big endian! you'll note ints being worked both big endian. failed @ bit shifting other way.


Comments

Popular posts from this blog

javascript - how to protect a flash video from refresh? -

android - Associate same looper with different threads -

visual studio 2010 - Connect to informix database windows form application -