每月项目

嘿嘿,这个月又做了一个project:

Python纯手工,实现字符串大数字加法!!!

完整代码:https://jihulab.com/Chenyun-Zhang/python-calc-and-objs/

废话不多说,上代码!

# import _baseobj._HiddenStr
import basic_func as functions
from basic_func import pad_with_zeros

class _HiddenStr(object):
def __init__(self, anystr):
try:
try:
self.__str = ‘.’.join(str(anystr).split(‘-‘))
except Exception:
self.__str = str(anystr)
except TypeError as te:
functions.richPrint(te)
except Exception as e:
functions.richPrint(e)

def get(self):
return self.__str

class NumStr:
“””
The Number formatted with Python str object.
“””

def __pre_init__(self, baseNum, splitParm: str):
self.numList = baseNum.split(splitParm)
self.intPart = _HiddenStr(self.numList[0])
self.decPart = _HiddenStr(self.numList[1])
self.numDecs = len(self.decPart.get())

def __init__(self, baseNum):

self.negFlag = False
if baseNum[0] == ‘-‘:
self.negFlag = True
baseNum = baseNum[1:]

if type(baseNum) == str:
if ‘.’ in baseNum:
self.__pre_init__(baseNum, ‘.’)

elif ‘,’ in baseNum:
self.__pre_init__(baseNum, ‘,’)

else:
try:
# The function ‘catchErr’ was written, but can’t use in this place.
int(baseNum)
self.numList = [baseNum, ”]
self.intPart = _HiddenStr(self.numList[0])
self.decPart = None
self.numDecs = 0

except TypeError as te:
functions.errOutPut(te)

except Exception as e:
functions.errOutPut(e)

elif type(baseNum) == float:
self.__init__(str(baseNum))

elif type(baseNum) == int:
self.__init__(str(baseNum))

else:
raise TypeError(‘The object it conv to type NumStr must in [str, float, int]’)

def get(self, numtoget=’all’):
if numtoget == ‘all’:
return self.numList

elif numtoget == ‘int’:
return self.intPart.get()

elif numtoget == ‘dec’:
return self.decPart.get()

class BigNumber:
“””
Class for handling operations with big numbers.
“””

def __init__(self, base_num):
self.number = NumStr(base_num)
self.num_list = self.number.numList
self.int_part = self.number.intPart
self.dec_part = self.number.decPart
self.num_decs = self.number.numDecs
self.neg_flag = self.number.negFlag

@staticmethod
def max_num_decimals(self, other):
“””
Returns the maximum number of decimals between two numbers.
“””
self_dec_flag = self.dec_part is not None
other_dec_flag = other.dec_part is not None

if self_dec_flag or other_dec_flag:
if self_dec_flag and not other_dec_flag:
return self.num_decs
elif other_dec_flag and not self_dec_flag:
return other.num_decs
elif self_dec_flag and other_dec_flag:
return max(self.num_decs, other.num_decs)
return None

@staticmethod
def num_zeros_start(number):
“””
Counts leading zeros in a number.
“””
num_zeros = 0
for char in number:
if char == ‘0’:
num_zeros += 1
else:
break
return num_zeros

@staticmethod
def num_zeros_end(number):
“””
Counts trailing zeros in a number.
“””
num_zeros = 0
i = len(number) – 1
while i >= 0 and number[i] == ‘0’:
num_zeros += 1
i -= 1
return num_zeros

def del_decimal_zeros(self, number):
“””
Removes trailing zeros from a decimal number.
“””
if “.” in number:
num_zeros = self.num_zeros_end(number)
if num_zeros != 0:
number = number[:-num_zeros]
if number[-1] == “.”:
number = number[:-1]
return number

@staticmethod
def adjust_decimal_strings(num1, num2):
“””
Adjusts decimal strings for arithmetic operations.
“””
if “.” in num1 or “.” in num2:
if “.” in num1 and “.” not in num2:
num1A, num1B = num1.split(“.”)
num1 = num1.replace(“.”, “”)
num2 += “0” * len(num1B)
elif “.” in num2 and “.” not in num1:
num2A, num2B = num2.split(“.”)
num2 = num2.replace(“.”, “”)
num1 += “0” * len(num2B)
elif “.” in num1 and “.” in num2:
num1A, num1B = num1.split(“.”)
num2A, num2B = num2.split(“.”)
num1 = num1.replace(“.”, “”)
num2 = num2.replace(“.”, “”)
num_zeros = abs(len(num1B) – len(num2B))
if len(num1B) < len(num2B):
num1 += “0” * num_zeros
elif len(num1B) > len(num2B):
num2 += “0” * num_zeros
return num1, num2

@staticmethod
def make_pairs(txt):
“””
Splits a string into pairs of characters.
“””
pairs = []
for i in range(0, len(txt), 2):
pairs.append(txt[i:i + 2])
return pairs

def add_big_numbers(self, other):
“””
Adds two big numbers.
“””

if other.neg_flag and (self.neg_flag == False):
# a+(-b) == a-b
other.neg_flag = False
temp = self – other
other.neg_flag = True
return temp
elif self.neg_flag and (not other.neg_flag):
# (-a)+b == b-a
other.neg_flag = False
temp = other – self
self.neg_flag = True
return temp
else:
# a+b or (-a)+(-b)
num1 = ‘.’.join(self.number.get(‘all’))
num2 = ‘.’.join(other.number.get(‘all’))
if self.num_decs > other.num_decs:
num2 += ‘0’ * (self.num_decs – other.num_decs)
elif self.num_decs < other.num_decs:
num1 += ‘0’ * (other.num_decs – self.num_decs)

num1, num2 = self.adjust_decimal_strings(num1, num2)

max_len = max(len(num1), len(num2))
num1 = pad_with_zeros(num1, max_len)
num2 = pad_with_zeros(num2, max_len)

result = ”
carry = 0
for i in range(max_len – 1, -1, -1):
temp_sum = int(num1[i]) + int(num2[i]) + carry
carry = temp_sum // 10
result = str(temp_sum % 10) + result

if carry != 0:
result = str(carry) + result

max_decs = self.max_num_decimals(self, other)
if max_decs is not None:
result = ‘.’.join(functions.splitAt(result, max_decs))

# (-a)+(-b) == -(a+b)
if self.neg_flag and other.neg_flag:
temp = BigNumber(self + other)
temp = – temp
return temp
else:
# std a+b
return BigNumber(result)

def sub_big_numbers(self, other):
“””
Subtracts two big numbers.
“””
if other.neg_flag and (not self.neg_flag):
other.neg_flag = False
temp = self + other
other.neg_flag = True
return temp
elif self.neg_flag and (not other.neg_flag):
self.neg_flag = False
temp = other – self
self.neg_flag = True
return temp
elif self.neg_flag and other.neg_flag:
other.neg_flag = False
self.neg_flag = False
temp = other – self
other.neg_flag = True
self.neg_flag = True
return self
else:
num1 = ‘.’.join(self.number.get(‘all’))
num2 = ‘.’.join(other.number.get(‘all’))
if self.num_decs > other.num_decs:
num2 += ‘0’ * (self.num_decs – other.num_decs)
elif self.num_decs < other.num_decs:
num1 += ‘0’ * (other.num_decs – self.num_decs)

num1, num2 = self.adjust_decimal_strings(num1, num2)

max_len = max(len(num1), len(num2))
num1 = pad_with_zeros(num1, max_len)
num2 = pad_with_zeros(num2, max_len)

result = ”
borrow = 0
for i in range(max_len – 1, -1, -1):
temp_sub = int(num1[i]) – int(num2[i]) – borrow
if temp_sub < 0:
temp_sub += 10
borrow = 1
else:
borrow = 0
result = str(temp_sub) + result

result = result.lstrip(‘0’)
stack = self.max_num_decimals(self, other)
if self.max_num_decimals(self, other) is not None:
result = result[:-stack] + ‘.’ + result[-stack:]

if result[0] == ‘.’:
result = ‘0’ + result

if float(num2) > float(num1):
result = BigNumber(result)
result.neg_flag = True
return result

return BigNumber(result)

def multiply_big_numbers(self, other):
“””
Multiplies two big numbers.
“””
if self.neg_flag and other.neg_flag \
or (not self.neg_flag and not other.neg_flag):
num1 = ‘.’.join(self.number.get(‘all’))
num2 = ‘.’.join(other.number.get(‘all’))
num1, num2 = self.adjust_decimal_strings(num1, num2)
result = str(int(num1) * int(num2))

total_decs = self.num_decs + other.num_decs
if total_decs > 0:
result = result[: -total_decs] + ‘.’ + result[-total_decs:]

result = result.rstrip(‘0’).rstrip(‘.’)
return BigNumber(result)
else:
snf = False
if self.neg_flag:
snf = True

self.neg_flag = False
other.neg_flag = False
temp = -(self * other)

if snf is not None:
self.neg_flag = True
else:
other.neg_flag = True

return temp

def divide_big_numbers(self, other, precision=10):
“””
Divides two big numbers.
“””
if self.neg_flag and other.neg_flag \
or (not self.neg_flag and not other.neg_flag):
num1 = ‘.’.join(self.number.get(‘all’))
num2 = ‘.’.join(other.number.get(‘all’))
num1, num2 = self.adjust_decimal_strings(num1, num2)

total_decs = self.num_decs – other.num_decs
quotient, remainder = divmod(int(num1), int(num2))
result = str(quotient)
remainder = str(remainder).rjust(precision, ‘0’)

if total_decs > 0:
result = result + ‘.’ + remainder[:total_decs]
else:
result = result.rjust(-total_decs, ‘0’) + ‘.’ + remainder[:precision]
result = result[:precision + 2]

result = result.rstrip(‘0’).rstrip(‘.’)
return BigNumber(result)
else:
snf = False
if self.neg_flag:
snf = True

self.neg_flag = False
other.neg_flag = False
temp = -(self / other)

if snf is not None:
self.neg_flag = True
else:
other.neg_flag = True

return temp

def __truediv__(self, other):
“””
Implements the true division operation (/) for BigNumber objects.
“””
return self.divide_big_numbers(other)

def __floordiv__(self, other):
“””
Implements the floor division operation (//) for BigNumber objects.
“””

result = self / other

stack = result.number.get(‘all’)
stack[-1] = stack[-1] + ‘0’

if result.neg_flag:
stack = ‘-‘ + stack[0]

return BigNumber(stack)

def __add__(self, other):
“””
Implements the addition operation (+) for BigNumber objects.
“””
return self.add_big_numbers(other)

def __sub__(self, other):
“””
Implements the subtraction operation (-) for BigNumber objects.
“””
return self.sub_big_numbers(other)

def __mul__(self, other):
“””
Implements the multiplication operation (*) for BigNumber objects.
“””
return self.multiply_big_numbers(other)

def __pos__(self):
return self

def __neg__(self):
if self.neg_flag:
self.neg_flag = False
else:
self.neg_flag = True

return self

def __str__(self):
“””
Returns the string representation of the BigNumber object.
“””
stack = ‘.’.join(self.number.get(‘all’))

if self.neg_flag:
return ‘-‘ + stack
else:
return stack

def __repr__(self):
“””
Returns the formal string representation of the BigNumber object.
“””
return self.__str__

想下载完整源代码的去https://jihulab.com/Chenyun-Zhang/python-calc-and-objs 就可以了!


了解 Clouds 的更多信息

订阅后即可通过电子邮件收到最新文章。


留下评论

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理