# TheLongDecimalClass # CS 1110 profs, Spring 2016 # May 2016 """ Contains a class that supports long decimal addition and multiplication. """ from TheLongIntClass import * class LongDecimal(object): """ Attributes: Whole: the whole number part [LongInt] Fract: the fraction part [LongInt w/out trailing zeroes ] UPDATE (Mon May 9): Fract's String should always have length >= 1, and should contain no extra trailing zeroes. For example, '0' is allowed; "", None, and '04000' are not allowed. """ def __init__(self,x): """ PreC: x can be either a string that is comprised of digits and at most one decimal point. or a valid nonnegative int or float literal, i.e., 37 , .37 , 37. or a reference to a LongDecimal object. UPDATES:for the purposes of this assignment, assume input is not in scientific notation. """ if isinstance(x,LongDecimal): self.Whole = LongInt(x.Whole.getString()) self.Fract = LongInt(x.Fract.getString()) self.fix_trailing() return if isinstance(x,float) or isinstance(x,int): x = str(x) k = x.find('.') if k==-1 or k==len(x)-1: self.Whole = LongInt(x) self.Fract = LongInt('0') else: self.Whole = LongInt(x[:k]) self.Fract = LongInt(x[k+1:]) self.fix_trailing() def getWhole(self): """Returns Whole as a string""" return self.Whole.getString() def getFract(self): """Returns Fract as a string""" return self.Fract.getString() def __str__(self): return self.getWhole()+'.'+ self.getFract() def __add__(self,other): """ Returns the sum of self and other as a LongDecimal PreC: other is a reference to a LongDecimal or LongInt object. """ if isinstance(other,LongDecimal): return self.Add(other) else: A = LongDecimal(other.getString()) return self.Add(A) # helper method # Makes use of times10 from LongInt def Add(self, other): """ Returns the sum of self and other as a LongDecimal PreC: other is a reference to a LongDecimal . """ nAFrac = len(self.getFract()) # number of digits in fractional part nBFrac = len(other.getFract()) A = LongInt(self.getWhole()+self.getFract()) # a string without a decimal point B = LongInt(other.getWhole()+other.getFract()) # get A and B's Fracts to line up. if nAFrac < nBFrac: A.times10(nBFrac-nAFrac) else: B.times10(nAFrac-nBFrac) sum_string = (A+B).getString() if nAFrac < nBFrac: dec_place = len(sum_string) - nBFrac else: dec_place = len(sum_string) - nAFrac adjusted_string = (sum_string[:dec_place] + '.' + sum_string[dec_place:]) return LongDecimal(adjusted_string).fix_trailing() # helper method - alternate implementation w/out using # times10 method of LongInt, uses helper function def Add2(self,other): """ Returns the sum of self and other as a LongDecimal PreC: other is a reference to a LongDecimal . """ # Idea: use LongInt addition, working around the fact # that LongInts "don't have decimal points" in them. # Suppose that "x_shorter" is the LongDecimal with fewer digits # in its Fract, and "x_longer" is the one with more digits in # its Fract. Example: x_shorter is 1234.56, x_longer is 29.2983 . # (a) 29.2983 -> "292983", a string "longer" with no decimal # (b) 1234.56 -> "12345600", a strong "shorter" with extra 0s # (c) add corresponding longints: # 12638583 # (d) get the string "12638583" and make it a LongDecimal # with number of digits in its Fract same as for longer: # Whole: 1263 Fract: 8583 nAFrac = len(self.getFract()) # number of digits in fractional part nBFrac = len(other.getFract()) A = self.getWhole()+self.getFract() # a string without a decimal point B = other.getWhole()+other.getFract() if nAFrac<nBFrac: # (nBFrac-nAFrac)*'0' is the number of zeroes needed to "pad" A # so that the fractional parts have the same length. # Example: for 1234.56 + 29.29837, we add 3 '0's to '123456': # 123456000 + 2929837 = 126385837 return AddLongerToShorter(B, A+(nBFrac-nAFrac)*'0', nBFrac) else: return AddLongerToShorter(A, B+(nAFrac-nBFrac)*'0', nAFrac) def __mul__(self,other): """ Returns the product of self and other as a LongDecimal PreC: other is a reference to a LongDecimal or LongInt object. """ if isinstance(other,LongDecimal): return self.Mult(other) else: A = LongDecimal(other.getString()) return self.Mult(A) # helper method def Mult(self,other): """ Returns the product of self and other as a LongDecimal PreC: other is a reference to a LongDecimal . Note: calls fix_trailing for the result """ nA = len(self.getFract()) nB = len(other.getFract()) A = self.getWhole() + self.getFract() B = other.getWhole() + other.getFract() C = LongInt(A)*LongInt(B) s = C.getString() k = len(s)-(nA+nB) return LongDecimal(s[:k]+'.'+s[k:]).fix_trailing() # helper method def fix_trailing(self): """Remove trailing zeroes from Fract of LongDecimal ld. If removing all the trailing zeroes would leave an empty string, set the Frac String to "0". Returns self (as a convenience to the caller). PreC: self.Fract.String is a string.""" self.Fract.String = self.Fract.String.rstrip('0') if len(self.Fract.String) == 0: self.Fract.String = "0" return self # helper function for Add2 above def AddLongerToShorter(longer, short, n_long): """Helper function for addition. Not for general use. Helper for Add2. longer = (a); short = (b). See comments for Add2 method. Note: calls fix_trailing method for the result""" # part (c) sum = LongInt(short) + LongInt(longer) # part (d) sum_string = sum.getString() dec_place = len(sum_string) - n_long return LongDecimal(sum_string[:dec_place] + '.' + sum_string[dec_place:]).fix_trailing() def main(): print 'section 2.3 output' x = LongDecimal(1234.56789) y = LongDecimal('398948937.3389493374') z = x*y print z x = LongDecimal(111.1111) y = LongDecimal(22.22) z = x+y print z x = LongDecimal(12345.56789) y = LongInt(1000) z = x+y print z x = LongDecimal('123456789.123456789') y = LongInt(1000) z = x*y print z y = LongDecimal(111.1111) x = LongDecimal(22.22) z = x+y print z #x = raw_input('x: ') #y = raw_input('y: ') x = '123456789.123456789' y = 1000 xLD = LongDecimal(x) yLD = LongDecimal(y) zLD = LongDecimal(y) print '\nFirst round' print xLD print yLD print zLD print '\nSecond round' print float(x)+float(y) sumLD = xLD + yLD print sumLD print '\nThird round' print float(x)*float(y) prodLD = xLD*yLD print prodLD print '\nFourth round' d = 12343726 dLI = LongInt(d) z = xLD + dLI print z print float(x)+d z = xLD*dLI print z print float(x)*d if __name__ == '__main__': main()