Search This Blog

2025/02/11

Long Division without rounding in python

 

 
Though Each language has sufficient datatypes yet for certain situation we need 
more mathematical datatypes,I made an attempt to create division algorithm for 
integer which does not rely on rounding end digits or truncating.
 
The limitation of algorithm is due to inherent behavior of python datatype to 
round fraction especially in case float & inability of Decimal to extract 
required fractions natively.
 
Code: 
 
from decimal import Decimal, getcontext

decimalDivident: int = 918
decimalDivisor: int = 139


# decimalDivident: int = 22
# decimalDivisor: int = 7
counter:int = 0;



print(f"Dividing:'{decimalDivident}' by '{decimalDivisor}'")

class RecurringDecimal:
def __init__(self, decimalValue: str, repeatStart: int, repeatEnd: int,stringValue:float):
self.decimalValue = decimalValue # String representation of the decimal
self.stringValue = stringValue # String representation of the decimal
self.repeatStart = repeatStart # Index where repeating part starts
self.repeatEnd = repeatEnd # Index where repeating part ends

def __repr__(self):
return f"RecurringDecimal(decimal='{self.decimal_value}', repeat_start={self.repeat_start}, repeat_end={self.repeat_end})"

def getDivision(divisor: int,divident:int,requiredDecimalFraction:int) -> RecurringDecimal:
division:int = 0
decimalDivision=0.0
remainder:int = 0
repeateEndIndex:int=-1
immediateDivision:int = 0
fractionPosition:int=-1
noOfDecimalAfterFraction:int=0
noOfDigitsInDivision:int=0
noOfDigitsAfterDecimal:int=0
repeateStartIndex:int=-1
reminderList:list=[]
enhancedDouble:RecurringDecimal

try:
print(f"*requiredDecimalFraction:'{requiredDecimalFraction}'")
while noOfDecimalAfterFraction < requiredDecimalFraction:
remainder = divident % divisor
immediateDivision = divident // divisor

if not remainder in reminderList:
reminderList.append(remainder)
elif remainder in reminderList and repeateStartIndex == -1:
repeateStartIndex = reminderList.index(remainder)
repeateEndIndex = len(reminderList) - repeateStartIndex -1


if(immediateDivision > 0):
division = division * 10 + immediateDivision
else:
division = division * 10

# print(f"*division:'{division}'")
divident = remainder

# print(f"#Before Inner While Loop:")
# print(f"#remainder:'{remainder}'")
# print(f"#divisor:'{divisor}'")

#print(f"In Inner While Loop:")
while remainder < divisor:
noOfDigitsAfterDecimal +=1
remainder = remainder * 10
divident = remainder

if fractionPosition == -1:
fractionPosition = len(str(division))

# print(f"##remainder:'{remainder}'")
# print(f"##divisor:'{divisor}'")
# print(f"##divident:'{divident}'")

if fractionPosition != -1:
noOfDecimalAfterFraction = noOfDecimalAfterFraction + 1

# print(f"**After Inner While Loop:")

if requiredDecimalFraction == noOfDecimalAfterFraction:
# print(f"--->No Of Decimal After Fraction'{noOfDecimalAfterFraction}'")
# print(f"--->Required Fractions Received")
break

if remainder ==0:
# print(f"--->Reminder Become Zero'")
break

# print(f"$$$$ division:'{division}'")
noOfDigitsInDivision = len(str(division))

# print(f"$$$$ fractionPosition:'{fractionPosition}'")
# print(f"$$$$ noOfDigitsInDivision:'{noOfDigitsInDivision}'")

if fractionPosition != -1:
decimalDivision =division / (10 ** (noOfDigitsInDivision - fractionPosition))

num_str = str(Decimal(decimalDivision).normalize())
decimal_part = num_str.split(".")[1] if "." in num_str else ""

print("%%% decimal_part:='{decimal_part}'")

if repeateEndIndex > 0:
stringDivision = num_str.split(".")[0] + "." + decimal_part[:repeateStartIndex + repeateEndIndex+1].ljust(repeateStartIndex + repeateEndIndex+1, '0')
else:
stringDivision = num_str.split(".")[0] + "." + decimal_part[:requiredDecimalFraction].ljust(requiredDecimalFraction, '0')


enhancedDouble=RecurringDecimal(decimalDivision,repeateStartIndex,repeateEndIndex,stringDivision)


print(f"$$$$ noOfDigitsAfterDecimal='{noOfDigitsAfterDecimal-1}' immediateDivision='{immediateDivision}'")
print(f"$$$$ repeateStartIndex='{repeateStartIndex}' repeateEndIndex='{repeateEndIndex}'")

return enhancedDouble
except ZeroDivisionError as e:
print("Error:", e)
raise ZeroDivisionError("Division by zero is not allowed.")

enhancedDouble:RecurringDecimal = getDivision(decimalDivisor,decimalDivident,22)
print(f"Division Result:'{enhancedDouble.decimalValue}',Recurring Start Point:'{enhancedDouble.repeatStart}' Recurring End Point:'{enhancedDouble.repeatEnd}' String Value '{enhancedDouble.stringValue}'")


No comments:

Post a Comment