2

I need a class holding 1000 decimal digits to calculate something like pi number in a series. Taking time is not important. How can I define __add__ & ... functions to do this? For example I need a value can hold this number: 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113

:))

This number using decimal.Decimal shows like this:

from decimal import Decimal as dc
>>> x=dc(3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113)
>>> x
Decimal('3.141592653589793115997963468544185161590576171875')

But I need a new class holding all DIGITS and I can use adding, dividing and ... functions in it like 2+1 and pi number is an example of that and exactly I don't need to calculate pi number I wanted to calculate extra large decimal numbers!

roippi
  • 25,533
  • 4
  • 48
  • 73
hamidfzm
  • 4,595
  • 8
  • 48
  • 80

4 Answers4

6

You have to set a context with 1000 decimal digits:

context = decimal.Context(prec=1000)
decimal.setcontext(context)

From now on computations will use 1000 digits precision.

Example:

>>> decimal.setcontext(decimal.Context(prec=1000))
>>> pi = decimal.Decimal('3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113')
>>> pi
Decimal('3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113')
>>> pi + 2
Decimal('5.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113')

Note that:

  • You have to use strings to initialize the Decimal because if you use a float the interpreter will have to truncate it first. (also I believe only the most recent versions of decimal accept a float argument. In older versions you had to use Decimal.from_float instead).
  • The decimal digits are preserved during calculations.

You can also use the context locally via the localcontext contextmanager:

context = decimal.Context(prec=1000)

with decimal.localcontext(context):
    # here decimal uses 1000 digits for computations
    pass

# here the default context is restored.
Bakuriu
  • 98,325
  • 22
  • 197
  • 231
1

You made the mistake of initialising the Decimal object with a double which can't represent your big number.

So instead of saying:

x=dc(3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113)

...which has exactly the same effect as:

x=dc(3.1415926535897932384626433832795)

...initialise from a string:

x=dc('3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113')

and you'll get the expected result with full precision.

Kos
  • 70,399
  • 25
  • 169
  • 233
  • If I use something like x+dc(2) the program will represent this number: Decimal('5.141592653589793238462643383') – hamidfzm Nov 14 '13 at 15:43
  • Yes, `x` is a normal object of type `Decimal` and it has arbitrary precision. Your issue was the limited precision of the number you've passed as a parameter to its constructor. – Kos Nov 14 '13 at 15:44
  • So what I have to do? I have this large decimal number and I want add some number like 2. – hamidfzm Nov 14 '13 at 15:46
  • Treat it like any other number, `x+=2`. [Read the Decimal docs](http://docs.python.org/2/library/decimal.html) – Kos Nov 14 '13 at 16:01
  • As I said before the other decimal numbers will disappear and python shows `Decimal('5.141592653589793238462643383')` – hamidfzm Nov 14 '13 at 16:09
  • You need to adjust the context to your desired precision, see http://docs.python.org/2/library/decimal.html#quick-start-tutorial – Kos Nov 14 '13 at 16:16
  • @HamidFzM: `x = Decimal('3.14...thousand digits')` -> `x` holds thousand digits. `x += 2` -> `x` is rounded to current precision (`decimal.getcontext().prec`). – jfs Dec 01 '13 at 18:01
0

My try. Might NOT be very good.

class pi:
    def __init__(self):
        self.pi_digits = ['1', '4', '1', '5', '9', '2', '6'] # pi = 3.1415926
    def __repr__(self):
        return '3.'+''.join(self.pi_digits)
    def add(self, digit):
        digit = str(digit)
        if digit.isdigit():
            self.pi_digits.append(digit)
        else:
            raise TypeError

my_pi = pi()
my_pi.add(3)
my_pi.add(5)
print (my_pi)

Output

3.141592635

PS - This is just to give you a rough idea of how you might go about doing things.

shad0w_wa1k3r
  • 12,955
  • 8
  • 67
  • 90
0

This function will give you string of value based on numerator (numer) and denominator (deno) and precision which can be used for any fractional number not just for pi. For pi, you can just use 22/7 and any precision you want.

def pi_accur(numer,deno,precision):
    pi_holder=[]
    while (precision>=1):
        pi_holder.append(int(numer/deno))
        numer=10*(numer%deno)
        precision=precision-1

    new_val=str(pi_holder[0])+'.'
    for i in pi_holder[1:]:
        new_val=new_val+str(i)
    return new_val

>>> pi_accur(22,7,9)
     '3.14285714'

>>>pi_accur(22,7,15)
   '3.14285714285714'
Jack_of_All_Trades
  • 10,942
  • 18
  • 58
  • 88
  • @rogaos: My point was not to identify the difference between actual pi and 22/7 which I know there is a difference but just to assist the OP in finding the way to store the values of terms such as 22/7 (close to pi) in a way he wants. – Jack_of_All_Trades Nov 14 '13 at 18:30
  • I downvoted because I found that point very unclear; pi is decidedly not a fractional number. if you edit your post accordingly, I'll rescind. Note that if he wants 1000 (correct) decimal digits, he might need a 1000 digit numerator, which doesn't seem to be a sustainable technique. And doesn't the Fractions module already do this? – vroomfondel Nov 15 '13 at 08:34