[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Bit twiddling floating point numbers

Jeff.Goldfinkle@gmail.com

3/5/2008 8:26:00 PM

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?
9 Answers

Grant Edwards

3/5/2008 8:38:00 PM

0

On 2008-03-05, Jeff.Goldfinkle@gmail.com <Jeff.Goldfinkle@gmail.com> wrote:

> 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: & | ~

--
Grant Edwards grante Yow! Half a mind is a
at terrible thing to waste!
visi.com

Grant Edwards

3/5/2008 8:49:00 PM

0

On 2008-03-05, Grant Edwards <grante@visi.com> wrote:
> On 2008-03-05, Jeff.Goldfinkle@gmail.com <Jeff.Goldfinkle@gmail.com> wrote:

>> Any suggestions?
>
> Just use the bitwise and/or/not operators: & | ~

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

--
Grant Edwards grante Yow! All of life is a blur
at of Republicans and meat!
visi.com

Jeff.Goldfinkle@gmail.com

3/5/2008 8:51:00 PM

0

On Mar 5, 10:48 pm, Grant Edwards <gra...@visi.com> wrote:
> On 2008-03-05, Grant Edwards <gra...@visi.com> wrote:
>
> > On 2008-03-05, Jeff.Goldfin...@gmail.com <Jeff.Goldfin...@gmail.com> wrote:
> >> Any suggestions?
>
> > Just use the bitwise and/or/not operators: & | ~
>
> Oh, I forgot to mention the shift operators << and >>
>
> --
> Grant Edwards grante Yow! All of life is a blur
> at of Republicans and meat!
> visi.com

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

Grant Edwards

3/5/2008 8:59:00 PM

0

On 2008-03-05, Jeff.Goldfinkle@gmail.com <Jeff.Goldfinkle@gmail.com> wrote:

> 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-poin...
http://steve.hollasch.net/cgindex/coding/ieee...
http://www.psc.edu/general/software/packages/ieee...

--
Grant Edwards grante Yow! Well, I'm INVISIBLE
at AGAIN ... I might as well
visi.com pay a visit to the LADIES
ROOM ...

Mark Dickinson

3/5/2008 9:07:00 PM

0

On Mar 5, 3:25 pm, "Jeff.Goldfin...@gmail.com"
<Jeff.Goldfin...@gmail.com> wrote:
> 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:

>>> m, e = frexp(pi)
>>> m
0.78539816339744828
>>> e
2
>>> int(m*2**53)
7074237752028440L

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

Mark

Mensanator

3/5/2008 9:28:00 PM

0

On Mar 5, 2:25 pm, "Jeff.Goldfin...@gmail.com"
<Jeff.Goldfin...@gmail.com> wrote:
> 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.

>>> import gmpy

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

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

# seperate the characteristic from the mantissa
>>> fs = f2.split('.')

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

# convert the string back to a base 10 float
>>> f4 = gmpy.mpf(f3,0,2)
>>> print f4
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

Jeff.Goldfinkle@gmail.com

3/6/2008 7:21:00 AM

0

On Mar 5, 11:27 pm, Mensanator <mensana...@aol.com> wrote:
> On Mar 5, 2:25 pm, "Jeff.Goldfin...@gmail.com"
>
> <Jeff.Goldfin...@gmail.com> wrote:
> > 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.
>
> >>> import gmpy
>
> # create a base 10 float>>> f = gmpy.mpf('123.456')
> >>> f
>
> mpf('1.23456e2')
>
> # format in base 2, fixed point>>> f2 = gmpy.fdigits(f,2,0,0,99)
> >>> f2
>
> '1111011.01110100101111000110101001111110111110011101101100100010111'
>
> # seperate the characteristic from the mantissa
>
> >>> fs = f2.split('.')
>
> # re-assemble with the mantissa truncated to desired # of bits>>> f3 = fs[0]+'.'+fs[1][:4]
> >>> f3
>
> '1111011.0111'
>
> # convert the string back to a base 10 float>>> f4 = gmpy.mpf(f3,0,2)
> >>> print f4
>
> 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.

Bryan Olson

3/6/2008 9:01:00 AM

0

Mark Dickinson wrote:
> Jeff Goldfin wrote:
>> 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:
>
>>>> m, e = frexp(pi)
>>>> m
> 0.78539816339744828
>>>> e
> 2
>>>> int(m*2**53)
> 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)


--
--Bryan

Jeff.Goldfinkle@gmail.com

3/6/2008 9:01:00 PM

0

On Mar 6, 11:00 am, Bryan Olson <fakeaddr...@nowhere.org> wrote:
> Mark Dickinson wrote:
> > Jeff Goldfin wrote:
> >> 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:
>
> >>>> m, e = frexp(pi)
> >>>> m
> > 0.78539816339744828
> >>>> e
> > 2
> >>>> int(m*2**53)
> > 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)
>
> --
> --Bryan
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