precision problems in base conversion of rational numbers

mensanator at aol.com mensanator at aol.com
Thu Jul 7 13:07:57 EDT 2005



Raymond Hettinger wrote:
> > > For a simple example, convert both 10247448370872321 and
> > > 10247448370872319 from base ten to 4 digits of hex.  The calculations
> > > need to be carried out to 15 places of hex (or 17 places of decimal)
> > > just to determine whether the fourth hex digit is a 7 or 8:
> > >
> > >     >>> hex(10247448370872321)
> > >     '0x24680000000001L'
> > >     >>> hex(10247448370872319)
> > >     '0x2467ffffffffffL'
> >
> > I don't understand your simple example.
> >
> > log(10)/log(16) = 0.83048202372184058696757985737235
> >
> > Multiplying by the number of decimal digits (17) gives
> >
> > 14.11819440327128997844885757533
> >
> > Rounding up to an integer digit count, we need need 15 hex digits.
> > Isn't that exactly what you concluded? Where does that 4 hex digit
> > stuff come from?
>
> It is part of the OP's problem spec.  Given a number x (which may be a
> decimal, float, long integer, or rational), a base b, and a desired
> precision p, compute the conversion to p-digits:
>
>   >>> convert(x=10247448370872319L, b=16, p=4)
>   '24680000000000'

But you haven't explained why you are using p=4. The OP's problem
is that he's doing convert(x=10247448370872319L, b=16, p=17).
So of course it's going to be wrong because base 16 numbers are
bigger than base 10 numbers. By trying to use the same precision
with different bases, he's asking for more precision in the base 17
number than what exists in the base 10 number.

>
> He wanted to know what decimal precision he needed to set to make the
> conversion accurate to the last place.  The required precision for
> intermediate calculations depends on how close x is to a representable
> value in the target base.  The 16 digits are not known a priori since x
> may be a rational, float, or decimal.  For instance, an internal
> precision of 17 digits would also be needed for other nearby values of
> x:
>
>   >>> convert(x=Decimal("10247448370872319.000000001", b=16, p=4)
>   '24680000000000'

Now your base 10 number has 26 digits. So shouldn't your convert be
using p=22?

>
> The number 17 does not just pop-out of a simple logarithm.

It most certainly does

>>> print floor(math.log10(10247448370872319)) + 1
17.0


> How many
> internal digits of precision do you need for convert(math.pi, b=16,
> p=5)?

I think I would need 7.

Because
>>> print math.log(16)/math.log(10)*5
6.02059991328


>>> from gmpy import *
>>> import math
>>> print math.pi
3.14159265359

Using math.pi

>>> print fdigits(math.pi,16,5)
3.243f at 0

Using only seven digits

>>> print fdigits(mpf("3.141593"),16,5)
3.243f at 0

I don't see any problem.

> If the result falls closely between reprentable values, the OP
> may need to set his "magic number" to something larger than you would
> have predicted.
>
> If you want insight into why the OP's problem statement is deeper than
> it appears, then ponder the mystery of why the following returns False:
>
>   >>> x = 554459760520464551937111727196883414687442277344893869152167
>   >>> float(x) == float(str(x))
>   False

No big mystery. Isn't that why they added the Decimal module?

>
> Hint, the two different underlying routines are trying to compute,
> convert(x, b=2, p=53), without the benefit of arbitrary precision
> arithmetic.

Yep, sure is nice to have that.

>>> x = mpz(554459760520464551937111727196883414687442277344893869152167)
>>> float(x)==float(str(x))
True


> 
> 
> Raymond




More information about the Python-list mailing list