Compute pi to base 12 using Python?

Dan Bishop danb_83 at yahoo.com
Wed Apr 13 07:07:59 EDT 2005


Dick Moores wrote:
> I need to figure out how to compute pi to base 12, to as many digits
as
> possible. I found this reference,
<http://mathworld.wolfram.com/Base.html>,
> but I really don't understand it well enough.

How many stars are in "*************************"?

You probably answered "25".  This means that, for convenience, you've
broken down the row of stars into ********** + ********** + *****, that
is, 2 tens with 5 left over, which the base-10 numeral system denotes
as "25".

But there's no reason other than tradition why you should arrange them
into groups of 10.  For example, you could write it as ******** +
******** + ******** + *, or 3 eights plus 1.  In octal (base-8)
notation, this is written as "31"; the "tens" place in octal represents
eights.

In general, in the base-r numeral system, the nth digit to the left of
the ones digit represents r^n.  For example, in the binary number
11001, the place values for each digit are, right to left, 1, 2, 4, 8,
and 16, so the number as a whole represents
1×16+1×8+0×4+0×2+1×1=16+8+1=25.  This analogous to 25=2×10+5 in
base-10.

It's also possible to write it as 3×8+0×4+0×2+1×1 = 3001 base 2,
but by convention, base-r only uses the digits in range(r).  This
ensures a unique represenation for each number.  This makes "11001" the
unique binary representation for decimal 25.

Note that for bases larger than 10, the digits will be numbers that are
not single digits in base 10.  By convention, letters are used for
larger digits: A=10, B=11, C=12, ... Z=35.  For example, the number
(dec) 2005 = 1×12³+1×12²+11×12+1×1 is represented in base-12 by
"11B1".

Fractions are handled in a similar manner.  The nth place to the right
of the radix point (i.e., the "decimal point", but that term is
inaccurate for bases other than ten) represents the value radix**(-n).

For example, in binary,
0.1 = 1/2 = dec. 0.5
0.01 = 1/4 = dec. 0.25
0.11 = 1/2 + 1/4 = 3/4 = dec. 0.75
0.001 = 1/8 = dec. 0.125
0.01010101... = 1/4 + 1/16 + 1/64 + ... = 1/3
0.0001100110011... = 1/10 = dec. 0.1

The last row explains why Python gives:

>>> 0.1
0.10000000000000001

Most computers store floating-point numbers in binary, which doesn't
have a finite representation for one-tenth.  The above result is
rounded to 53 signficant bits
(1.100110011001100110011001100110011001100110011010×2^-4), which is
exactly equivalent to decimal
0.1000000000000000055511151231257827021181583404541015625, but gets
rounded to 17 significant digits for display.

Similarly, in base-12:

0.1 = 1/12
0.14 = 1/12 + 4/144 = 1/9
0.16 = 1/12 + 6/144 = 1/8
0.2 = 2/12 = 1/6
0.3 = 3/12 = 1/4
0.4 = 4/12 = 1/3
0.6 = 6/12 = 1/2
0.8 = 8/12 = 2/3
0.9 = 9/12 = 3/4
0.A = 10/12 = 5/6

Notice that several common fractions have simpler representations in
base-12 than in base-10.  For this reason, there are people who believe
that base-12 is superior to base-10.
(http://www.dozenalsociety.org.uk)

> Could someone show me how to do what I need?

You'll need 3 things:

(1) An algorithm for computing approximations of pi.

The simplest one is 4*(1-1/3+1/5-1/7+1/9-1/11+...), which is based on
the Taylor series expansion of 4*arctan(1).

There are other, faster ways.  Search Google for them.

(2) An unlimited-precision numeric representation.  The standard
"float" isn't good enough: It has only 53 bits of precision, which is
only enough for 14 base-12 digits.

The "decimal" module will probably work, although of course its base-10
internal representation will introduce slight inaccuracies.

(3) A function for converting numbers to their base-12 representation.

For integers, this can be done with:

DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def itoa(num, radix=10):
   is_negative = False
   if num < 0:
      is_negative = True
      num = -num
   digits = []
   while num >= radix:
      num, last_digit = divmod(num, radix)
      digits.append(DIGITS[last_digit])
   digits.append(DIGITS[num])
   if is_negative:
      digits.append("-")
   digits.reverse()
   return ''.join(digits)

For a floating-point number x, the representation with d "decimal"
places count be found by taking the representation of int(round(x *
radix ** d)) and inserting a "." d places from the right.




More information about the Python-list mailing list