Skip to content

Instantly share code, notes, and snippets.

@ryanjsfx
Created February 21, 2013 04:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanjsfx/5002193 to your computer and use it in GitHub Desktop.
Save ryanjsfx/5002193 to your computer and use it in GitHub Desktop.
class BigNumber(object):
"""BigNumber stores nonnegative integers.
BigNumber takes a string, of ints and only ints, creates an integer
(not long) representation of that many charactered string of ints.
Any negative int (in form of string) input will be made into the
absolute value (positive) integer equivalent of that input.
"""
def __init__(self,string_literal):
"""Inits BigNumber
Takes the string input and stores each character
in its own (always) unique variable.
Args:
string_literal: A string representation of
a large int. It is the input for init
BigNumber that is taken and made into a
corresponding, representative, integer.
Is type string.
Returns:
None
Raises:
KeyError: for when the global "i" is referenced
before assignment the first time a BigNumber
is created.
ValueError: if a string not of underlying type
int.
"""
if string_literal[0] == "-":
pop(string_literal[0])
# Removes the negative sign, if there, from the string # comment to left refers up
# representation of the int.
# Sets up a dummy counting variable i which is concatenated
# to the end of the counter variable "counter" so that the
# correct counter (and corresponding sequence of digits)
# can later be accessed in reference to which number created # comment to left refers down
# instance of BigNumber is such (that is, the first BigNumber
# instance, as first, has i = 0, which corresponds to
# counter0 = 1 which corresponds to (up to) 80,000 unique digit
# values available).
try:
globals()["i"] = globals()["i"] + 1
globals()["counter" + str(globals()["i"])] = globals()["counter" + str(globals()["i"] - 1)] + 80000
except KeyError as error:
globals()["i"] = 0
globals()["counter" + str(globals()["i"])] = 1
# Constructs a unique "max_digit" variable for each BigNumber
# instance created. Each max_digit variable has the value of # comment to left refers down
# the length of total digits in that BigNumber (needed for
# knowing how long to loop for).
globals()["max_digit" + "_" + str(globals()["counter" + str(globals()["i"])])] = len(string_literal)
print globals()["max_digit" + "_" + str(globals()["counter" + str(globals()["i"])])]
# Catches if a non-int string representation is given as input;
# otherwise, gives a unique (up to 80,000) variable name for each # refers below
# digit in the BigNumber
for x in xrange(0,globals()["max_digit" + "_" + str(globals()["counter" + str(globals()["i"])])] + 1):
try:
globals()["digits" + str(x) + "_" + str(globals()["counter" + str(globals()["i"])])] = int(string_literal[x-1])
except ValueError as error:
print "BigNumber does not accept any type of string besides int."
def print_number(self):
"""Prints a string that is the BigNumber representation of a large
ingeger.
Args:
None except for self.
Returns:
self.re_string_literal: The re-formed string representation of
the big int that was originally input to init BigNumber and is
now returned after its necessary information has been taken.
Returns type string
"""
self.re_string_literal = ""
for x in xrange (1, globals()["max_digit" + "_" + str(globals()["counter" + str(globals()["i"])])] + 1):
self.re_string_literal = self.re_string_literal + str(globals()["digits" + str(x) + "_" + str(globals()["counter" + str(globals()["i"])])])
return self.re_string_literal
def add_da_numbers(self, number_created_add1, number_created_add2):
"""Arithmetically adds two BigNumber instances.
Args:
self
number_created_add1: Refers to when the particular instance
of the BigNumber class was created (first = 0, second = 1...).
Necessary for selecting the correct maxDigits and stored digits
for that number that is to be added. Type int.
number_created_add2: See number_created_add1.
Returns:
Returns the addition of the two instances of the BigNumber
class as a string representative of the corresponding int.
Type string.
"""
if globals()["max_digit" + "_" + str(globals()["counter" + str(number_created_add1)])] > globals()["max_digit" + "_" + str(globals()["counter" + str(number_created_add2)])]:
ranger = globals()["max_digit" + "_" + str(globals()["counter" + str(number_created_add1)])]
else:
ranger = globals()["max_digit" + "_" + str(globals()["counter" + str(number_created_add2)])]
carryEr = 0
# adds the two numbers together, digit by digit. (refers below, not above)
for x in xrange(ranger, 0, -1):
globals()["summed_digit" + str(x)] = globals()["digits" + str(x) + "_" + str(globals()["counter" + str(number_created_add1)])] + globals()["digits" + str(x) + "_" + str(globals()["counter" + str(number_created_add2)])] + carryEr
carryEr = 0
if globals()["summed_digit" + str(x)] == 10:
carryEr = 1
globals()["summed_digit" + str(x)] = 0
elif globals()["summed_digit" + str(x)] > 10 and globals()["summed_digit" + str(x)] < 20:
carryEr = 1
globals()["summed_digit" + str(x)] = int(globals()["summed_digit" + str(x)]) - 10
re_string_literal_summed = ""
for x in xrange (1, ranger + 1):
re_string_literal_summed = re_string_literal_summed + str(globals()["summed_digit" + str(x)])
return re_string_literal_summed
def shift_left(self, number_created):
"""Arithmetically shifts the BigNumber instance to the left one digit.
Args:
number_created: Refers to when the particular instance
of the BigNumber class was created (first = 0, second = 1...).
Necessary for selecting the correct maxDigits and stored digits
for that number that is to be left shifted. Type int.
Returns:
Adds a digit (0) to the end of the BigNumber and returns
that larger BigNumber as a string representative of the
corresponding int. Type string.
"""
ranger = globals()["max_digit" + "_" + str(globals()["counter" + str(number_created)])]
globals()["digits" + str(ranger+1) + "_" + str(globals()["counter" + str(number_created)])] = 0
self.re_string_literal = self.re_string_literal + str(globals()["digits" + str(ranger+1) + "_" + str(globals()["counter" + str(number_created)])])
return self.re_string_literal
def shift_right(self, number_created):
"""Arithmetically shifts right the BigNumber instance by one digit.
Reduces the appropriate maxDigit by 1 so that the ones place is
shifted one to the right.
Args:
number_created: Refers to when the particular instance
of the BigNumber class was created (first = 0, second = 1...).
Necessary for selecting the correct maxDigits and stored digits
for that number that is to be right shifted. Type int.
Returns:
One less digit (old ones digit not printed) is returned as a
string representation of the corresponding integer. Tyep string.
"""
ranger = globals()["max_digit" + "_" + str(globals()["counter" + str(number_created)])]
ranger -= 1
self.re_string_literal = ""
for x in xrange (1, ranger + 1):
self.re_string_literal = self.re_string_literal + str(globals()["digits" + str(x) + "_" + str(globals()["counter" + str(number_created)])])
return self.re_string_literal
def main():
first_test=BigNumber("38921689416894156419816111145611984156")
print "\nHello first Big Number: ", first_test.print_number()
second_test = BigNumber("43634634634734732110000151449946100111")
print "\nHello second Big Number: ", second_test.print_number()
third_test = first_test.add_da_numbers(0,1)
print "\nHello sum of first and second Big Numbers: ", third_test
fourth_test = first_test.shift_left(0)
print "\n One shift left: ", fourth_test
fifth_test = second_test.shift_right(1)
print "\n One shift right: ", fifth_test
main()
# Exploration Questions:
"""1. In storing the integer data, there are advantages and disadvantages to
how you divide the contents of the BigNumber into manageable parts
(i.e.,  109). Using your coding decisions as context, explain why you
chose your approach to implement BigNumber. Contrast it with another approach
that you did not implement."""
# I chose to break up the initial string literal of the BigNumber into one
# variable per digit. I made this decision to make the addition simple; all
# I had to do was add the corresponding digits of the two BigNumbers, which
# is also how I add (I think) manually. This method also made it simple to
# perform right and left shifts.
# I chose this method of storing the values of BigNumber instead of storing,
# say, the eight digits at a time as separate variables because it was
# easier for me to see a way of implementing my method into code and
# because it seemed to me nicer to have access to each digit.
"""2. Of addition, subtraction, multiplication, and division, you were
instructed to implement only addition. What considerations are required
in the implementation of the other three operations? Does your existing
design allow for implementing those operations easily? Why or why not?"""
# As addition requires the consideration of carrying the tens digit,
# subtraction requires the consideration of 'borrowing'. I think I
# would be able to code 'borrowing' into my code without too much
# difficulty and this would be the only addition to my code
# necessary because my code stores each digit as a value and could
# therefore just follow manual subtraction: check if the numbers
# that would be subtracted would yield a negative value. If so then
# add ten to the top number and subtract again (giving a positive
# number) and activate a subtractor variable that would take off 1
# from the next digit unless that digit is 0. If the next digit is
# 0, it is likely that that digit will also need to borrow, so
# increment the subtractor to 2 and go through with the subtraction
# digit by digit.
# Multiplication would be a bit more difficult, but still fairly
# simple to implement; all I would have to do is use the same
# addition code, changing the plus to multiplies and take more
# scenarios into account: carry variable can take values up to 8
# and an additional for loop would be necessary to multiply the
# lower number digit by each digit of the upper number. But still,
# I think my code is set up in such a way that it would not be
# too difficult to set up that code.
# For division, my code could very easily solve for orders of
# magnitude by comparing the max digit values of each BigNumber.
# For more precise division, it would have to check what multplies
# the leading n numbers that the number being divided into would
# supply and then check which would be the greatest multiple not
# exceeding the value of the number doing the dividing. In other
# words, division would be fairly tough to implement. It took me
# quite a bit to think of how division would be done with any
# implementation (assuming only up to 9 digits could be stored per
# variable and the numbers being divided would be many more than
# 9 digits). However, I do believe that I could implement division
# with my code, though it would probably be fairly inefficient
# because it would have to cross check every number in the BigNumbers.
# Divying up the digits by 8 into variables would increase the
# efficiency 8 times over mine, so mine is not the best implementation
# for division, but I believe it could still be done.
"""3. Make a claim about the largest BigNumber you think you can store. Justify your claim (i.e.,
create a BigNumber object for that number)."""
# I think I can make a number as big as my computer can make... let's
# try a google.
## This is where I had the code for the call that made a BigNumber (using
## my above code) that I got up to 260,000 digits.
# (I'm not displaying the actual calls that I did because they were slowing my
# computer down and it took up a lot of space.
# (The below block of code was performed yesterday and therefore has today's
# revisions written in a bit.)
# Well, my code was able to print a number as large as my computer would let it
# (though not a google sadly). Up to 10,000 digits it only took my computer
# a few seconds to create and print the BigNumber (it started slowing down a bit
# at 40,000 but up to 100,000 was the same as 40,000 (about)), it took about 5 minutes to print 70,000 digits, and the above
# call's formatting (when it was displayed it was above) went to hell when
# I tried (not to run the code) but simply to copy and paste another 10,000 digits
# to up the antie to 80,000 (my computer is definitely at its limit; it is
# taking a whole second or so just to display the text that I'm typing now).
# Also, I just found out that the reason why it went to hell (I tried running it now)
# is because it says IndexError: string index out of range. So, it would seem
# that just as there is a max int that python can store, there is a max string
# (who's value is somewhere between 70,000 and 80,0000 characters).
# It would seem that the max characters allowed in a string varies by day,
# today it is 262,000. My computer is doing better today and printed that
# BigNumber in less than a minute. Also, the Wing editor can display 128 '2's
# per line.
"""4. The underlying long representations do exist in Python. In only this case, create large long
values and perform arithmetic operations with them. Compare and contrast your addition
implementation with that of adding the same integers (e.g., compare timings of both operations).
Explain your findings."""
# I am currently trying to make BigNumbers to use for the comparison that are
# not too large that I cannot display them below but are large enough that
# the two methods don't both give a time difference of "0.0"
# Well, it's not much, but I don't want to be displaying too big BigNumbers.
# Result: 366 digit BigNumbers added my way take 0.01 (about) seconds, whereas
# longs addition is still "0.0"
to_add1 = BigNumber("847483932028284374748349302029384747565464783392901902923938384748393202828437474834930202938474756546478339290190292393838474839320282843747483493020293847475654647833929019029239383847483932028284374748349302029384747565464783392901902923938384748393202828437474834930202938474756546478339290190292393838474839320282843747483493020293847475654647833929019029239383")
to_add2 = BigNumber("999999999922222222222777777777744444444440000000000111111111199999999992222222222277777777774444444444000000000011111111119999999999222222222227777777777444444444400000000001111111111999999999922222222222777777777744444444440000000000111111111199999999992222222222277777777774444444444000000000011111111119999999999222222222227777777777444444444400000000001111111111")
import time
start = time.time()
to_add1.add_da_numbers(2,3)
stop = time.time()
print ("my way: ", stop - start)
long1 = 847483932028284374748349302029384747565464783392901902923938384748393202828437474834930202938474756546478339290190292393838474839320282843747483493020293847475654647833929019029239383847483932028284374748349302029384747565464783392901902923938384748393202828437474834930202938474756546478339290190292393838474839320282843747483493020293847475654647833929019029239383
long2 = 999999999922222222222777777777744444444440000000000111111111199999999992222222222277777777774444444444000000000011111111119999999999222222222227777777777444444444400000000001111111111999999999922222222222777777777744444444440000000000111111111199999999992222222222277777777774444444444000000000011111111119999999999222222222227777777777444444444400000000001111111111
start = time.time()
long1 + long2
stop = time.time()
print "longs: ", stop-start
# (I did the below but am not including it now because it took up many lines.)
# Instead, the above are more manageable BigNumber(s).
# Adding 262,000 digit numbers my way, at least according to 'timeit' took
# 2.8610000610351562 (seconds I'm assuming, it doesn't say...). It said
# that longs took 0.0 seconds. Second time run, my way took 2.53 (about) seconds(?)
# and longs took 0.00999990 seconds(?)
# It would seem that I have found that my code's addition vs. long addition,
# at least up until about 300 digits, is about the same quickness. At 366 digits,
# my code starts taking a bit longer to add than longs and at the biggest I got,
# 262,000 digits, my code took signficantly longer (2.86 seconds my way (or possibly
# minutes, it didn't specify) versus 0.00999990 seconds (probably, though also
# possibly minutes).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment