Bit twiddling floating point numbers

  • Thread starter Jeff.Goldfinkle
  • Start date
J

Jeff.Goldfinkle

Hi All

Is there a simple way to twiddle the bits of a float? In particular, I
would like to round my float to the n most significant bits.

For example - 0.123 in binary is 0.000111111
Rounding to 4 bits I get 0.0001.

I can pack and unpack a float into a long
e.g.
struct.unpack('I',struct.pack('f',0.123))[0]
but then I'm not sure how to work with the resulting long.

Any suggestions?
 
G

Grant Edwards

Is there a simple way to twiddle the bits of a float? In particular, I
would like to round my float to the n most significant bits.

For example - 0.123 in binary is 0.000111111
Rounding to 4 bits I get 0.0001.

I can pack and unpack a float into a long
e.g.
struct.unpack('I',struct.pack('f',0.123))[0]
but then I'm not sure how to work with the resulting long.

Any suggestions?

Just use the bitwise and/or/not operators: & | ~
 
J

Jeff.Goldfinkle

Oh, I forgot to mention the shift operators << and >>

thanks for the reply but I'm still unsure as to how to continue. Using
the bitwise operators will help me deal with integers but I really
want to work with floats. For instance - which bits do I twiddle to
round my float to the nearest number of bits?

Jeff
 
G

Grant Edwards

thanks for the reply but I'm still unsure as to how to
continue. Using the bitwise operators will help me deal with
integers but I really want to work with floats.

In your original post, you said that you've got the values as
integers.
For instance - which bits do I twiddle to round my float to
the nearest number of bits?

The format of a float (actually Python uses doubles) depends on
your platform, but in all likelihood it's the IEEE-754 64-bit
format.

googling for "IEEE-754 format" finds some good references:

http://en.wikipedia.org/wiki/IEEE_floating-point_standard
http://steve.hollasch.net/cgindex/coding/ieeefloat.html
http://www.psc.edu/general/software/packages/ieee/ieee.html
 
M

Mark Dickinson

I can pack and unpack a float into a long
e.g.
struct.unpack('I',struct.pack('f',0.123))[0]
but then I'm not sure how to work with the resulting long.

Any suggestions?

One alternative to using struct is to use math.ldexp and math.frexp:
7074237752028440L

Then you can do your bit twiddling on int(m*2**53), before using
ldexp to 'repack' the float.

Mark
 
M

Mensanator

Hi All

Is there a simple way to twiddle the bits of a float? In particular, I
would like to round my float to the n most significant bits.

For example - 0.123 in binary is 0.000111111
Rounding to 4 bits I get 0.0001.

I can pack and unpack a float into a long
e.g.
struct.unpack('I',struct.pack('f',0.123))[0]
but then I'm not sure how to work with the resulting long.

Any suggestions?

Here's one.

# create a base 10 floatmpf('1.23456e2')

# format in base 2, fixed point'1111011.01110100101111000110101001111110111110011101101100100010111'

# seperate the characteristic from the mantissa
# re-assemble with the mantissa truncated to desired # of bits
'1111011.0111'

# convert the string back to a base 10 float123.4375

# check: print as base 2 and see how many digits are past radix point1111011.0111
 
J

Jeff.Goldfinkle

Is there a simple way to twiddle the bits of a float? In particular, I
would like to round my float to the n most significant bits.
For example - 0.123 in binary is 0.000111111
Rounding to 4 bits I get 0.0001.
I can pack and unpack a float into a long
e.g.
struct.unpack('I',struct.pack('f',0.123))[0]
but then I'm not sure how to work with the resulting long.
Any suggestions?

Here's one.

# create a base 10 float>>> f = gmpy.mpf('123.456')
mpf('1.23456e2')

# format in base 2, fixed point>>> f2 = gmpy.fdigits(f,2,0,0,99)
'1111011.01110100101111000110101001111110111110011101101100100010111'

# seperate the characteristic from the mantissa

# re-assemble with the mantissa truncated to desired # of bits>>> f3 = fs[0]+'.'+fs[1][:4]
'1111011.0111'

# convert the string back to a base 10 float>>> f4 = gmpy.mpf(f3,0,2)
123.4375

# check: print as base 2 and see how many digits are past radix point>>> print gmpy.fdigits(f4,2,0,0,99)

1111011.0111

excellent - thanks that does exactly what I need.
 
B

Bryan Olson

Mark said:
Jeff said:
I can pack and unpack a float into a long
e.g.
struct.unpack('I',struct.pack('f',0.123))[0]
but then I'm not sure how to work with the resulting long.

Any suggestions?

One alternative to using struct is to use math.ldexp and math.frexp:
7074237752028440L

Then you can do your bit twiddling on int(m*2**53), before using
ldexp to 'repack' the float.

Ah, those are handy. Jeff described his problem: "In particular,
I would like to round my float to the n most significant bits."
I think this works:

from math import frexp, ldexp, floor

def round_mantissa(x, nbits):
shifter = 1 << nbits
(m, e) = frexp(x)
m = floor(m * shifter + 0.5) / shifter
return ldexp(m, e)
 
J

Jeff.Goldfinkle

Mark said:
Jeff said:
I can pack and unpack a float into a long
e.g.
struct.unpack('I',struct.pack('f',0.123))[0]
but then I'm not sure how to work with the resulting long.
Any suggestions?
One alternative to using struct is to use math.ldexp and math.frexp:

Then you can do your bit twiddling on int(m*2**53), before using
ldexp to 'repack' the float.

Ah, those are handy. Jeff described his problem: "In particular,
I would like to round my float to the n most significant bits."
I think this works:

from math import frexp, ldexp, floor

def round_mantissa(x, nbits):
shifter = 1 << nbits
(m, e) = frexp(x)
m = floor(m * shifter + 0.5) / shifter
return ldexp(m, e)
Thanks for the help - your function seems to fit the bill even better
than gmpy since I don't need an external module. In my case I'll use
m = floor(m * shifter) / shifter instead of m = floor(m * shifter +
0.5) / shifter

Jeff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top