I had a thought ... (I know, call the newspapers).

gods1child alankarmisra at hotmail.com
Sun Jun 3 15:46:25 CEST 2001


would something like this work? it needs to be extended for other
arithmetic ops but thats trivial if the core approach is correct. I've
used the str representation of the numbers since it seems to
accurately depict what the value SHOULD be as a string and not the
stored numeric value. If the str depiction is incorrect in certain
cases, then the whole approach is wrong.

import types
import string
import sys

class money:
    def __init__(self, num):
        if isinstance(num, money):
            self.accuracy = num.accuracy
            self.__num = num.__num
        else:
            # accuracy upto n decimal places
            self.accuracy = 4
            # arg has to be a non-complex number
            self.checkArg(num)
            # remove the decimal point
            num_parts = string.split(str(num),'.')
            
            # no decimal point, int or long ?
            if len(num_parts)==1:
                # 'multiply' by pow(10,accuracy)          
                string_num = num_parts[0] + '0' * self.accuracy
                
            # decimal places exceed accuracy limit ?    
            elif len(num_parts[1]) > self.accuracy: 
                raise TooManyDecimalPlacesException
            else:
                # 'multiply' by pow(10,accuracy)
                string_num = string.join(num_parts,'') \
                    + '0' * (self.accuracy - len(num_parts[1]))  
            try:
                # try using the smallest holder
                self.__num = int(string_num) 
            except:
                self.__num = long(string_num)

    def __add__(self,num):
       if isinstance(num, money):
           try:
               # convert self.__num to long to avoid integer overflow
error
               return money((num.__num + long(self.__num))/10000.0)
           except TooManyDecimalPlacesException:
               raise ('Invalid argument ' + str(num) + \
                      '. Cannot work with > ' + \
                      str(self.accuracy) + ' decimal places.')
           except:
               print sys.exc_info()
               
       else: 
           self.checkArg(num)
           try:
               return money(num + (self.__num/10000.0))
           except TooManyDecimalPlacesException:
               raise ('Invalid argument ' + str(num) + \
                      '. Cannot work with > ' + \
                      str(self.accuracy) + ' decimal places.')
           except:
               print sys.exc_info()
               

    __radd__ = __add__           
       
    def checkArg(self, num):
       if not (
            type(num) is types.IntType or
            type(num) is types.LongType or
            type(num) is types.FloatType
        ):
           raise ValueError, 'Only non-complex numbers are allowed in
arithmetic operations for money'
                    
    def __str__(self):
        return str(self.__num/10000.0)
    
    __repr__ = __str__

class TooManyDecimalPlacesException(ValueError):
    pass

# Usage
print 'Evaluating val = money(1.0)  + .01 + .001 + .0001 + 1 + 1L'
val = money(1.0)  + .01 + .001 + .0001 + 1 + 1L
print 'Result:', val
print

print 'Evaluating isinstance(val, money)'
print 'Result:', isinstance(val, money)
print

print 'Evaluating anotherval = money(val): anotherval is val'
anotherval = money(val)
print 'Result:', anotherval is val



More information about the Python-list mailing list