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}'")


2025/02/10

Division using Matrix a failed attempt

def reverseNumber(n: int) -> int:
reversed_num = 0
while n > 0:
remainder = n % 10
reversed_num = reversed_num * 10 + remainder
n //= 10 # Floor division
return reversed_num

def create2DimensionalMatrix(rows: int, cols: int, default_value=0) -> list:
return [[default_value for _ in range(cols)] for _ in range(rows)]


def valueOfMatrix(valueMatrix: list) -> float:
returnValue:float=0
for i, row in enumerate(valueMatrix):
for j, value in enumerate(row):
returnValue = returnValue + valueMatrix[i][j]

return returnValue

decimalDividend: int = 918
decimalDivisor: int = 139
decimalDividendRevered: int = reverseNumber(decimalDividend)
decimalDivisorRevered: int = reverseNumber(decimalDivisor)

decimalDividendConstitutent:list=[]
decimalDivisorConstitutent:list=[]

while decimalDividendRevered > 0:
decimalDividendConstitutent.append(decimalDividendRevered%10)
decimalDividendRevered = int(decimalDividendRevered/10)

while decimalDivisorRevered > 0:
decimalDivisorConstitutent.append(decimalDivisorRevered%10)
decimalDivisorRevered = int(decimalDivisorRevered/10)

print(f"% Broken Dividend Decimal Into Constitutent Digits:'{decimalDividendConstitutent}'")
print(f"% Broken Divisor Decimal Into Constitutent Digits:'{decimalDivisorConstitutent}'")

decimalDividendConstitutentReversedList:list = decimalDividendConstitutent[::-1]
decimalDivisorConstitutentReversedList:list = decimalDivisorConstitutent[::-1]

numberOfDigitsInDecimalDividendReveredList:int = len(decimalDividendConstitutentReversedList)
numberOfDigitsInDecimalDivisorReveredList:int = len(decimalDivisorConstitutentReversedList)


divisionMatrix:list = create2DimensionalMatrix(numberOfDigitsInDecimalDividendReveredList,numberOfDigitsInDecimalDivisorReveredList)
remainderMatrix:list = create2DimensionalMatrix(numberOfDigitsInDecimalDividendReveredList,numberOfDigitsInDecimalDivisorReveredList)
valueMatrix:list = create2DimensionalMatrix(numberOfDigitsInDecimalDividendReveredList,numberOfDigitsInDecimalDivisorReveredList)


print(f"No Of Constitutent Digits In Dividend:'{numberOfDigitsInDecimalDividendReveredList}'")
print(f"No Of Constitutent Digits In Divisor: '{numberOfDigitsInDecimalDivisorReveredList}'")

print(f"Nexted Loop Starts Here")

division:int =0
reminder:int =0
k:int =0
valueDecimalFactor:float=0
valueDecimalDividerFactor:float=0
signFactor:int=0
borrowFactor:int=1

twoDimensionalMatrixRowCursorPlaceValue:int =0
twoDimensionalMatrixColumnCursorPlaceValue:int =0

dividentPlaceValue:int = 0
divisorPlaceValue:int = 0

# Assuming lists are of equal length
for i in reversed(range(len(decimalDividendConstitutentReversedList))):
for j in reversed(range(len(decimalDivisorConstitutentReversedList))):
print(f"------Iteration Start------")
print(f"Nexted Loop Cursor Position:")
print(f"i :{i}")
print(f"j :{j}")
print(f"abs(j-2) :{abs(j-2)}")
print(f"abs(i-2) :{abs(i-2)}")

twoDimensionalMatrixRowCursorPlaceValue =numberOfDigitsInDecimalDividendReveredList- i -1
twoDimensionalMatrixColumnCursorPlaceValue =numberOfDigitsInDecimalDivisorReveredList - j -1

if i < j: # Skip loop
print(f"# Skipping Iteration")
continue

print(f"# Decimal Cursored Dividend Digit: {decimalDividendConstitutentReversedList[i]},Cursor At Decimal Index {i}")
print(f"# Decimal Cursored Divisor Digit: {decimalDivisorConstitutentReversedList[j]},Cursor At Decimal Index {j}")

placeValueDividendConstituentReversedListCursoredDigit = decimalDividendConstitutentReversedList[i] * (10 ** i)
placeValueDivisorConstituentReversedListCursoredDigit = decimalDivisorConstitutentReversedList[j] * (10 ** j)

print(f"# Place Value Divisor Constituent Reversed List Cursored Digit: {placeValueDivisorConstituentReversedListCursoredDigit}")
print(f"# Place Value Dividend Constituent Reversed List Cursored Digit: {placeValueDividendConstituentReversedListCursoredDigit}")

# if placeValueDivisorConstituentReversedListCursoredDigit > placeValueDividendConstituentReversedListCursoredDigit : # Skip loop
# print(f"# Skipping Iteration")
# continue



if abs(j-2) < abs(i-2): #col index less than row index
print(f"## Skipping Iteration")
continue

if(decimalDivisorConstitutentReversedList[j] > decimalDividendConstitutentReversedList[i]):
borrowFactor = -1
else:
borrowFactor = 1


division = borrowFactor * placeValueDividendConstituentReversedListCursoredDigit/placeValueDivisorConstituentReversedListCursoredDigit
reminder = placeValueDividendConstituentReversedListCursoredDigit % placeValueDivisorConstituentReversedListCursoredDigit



print(f"## Dividend Constituent Digit Revered List Cursored Digit: {decimalDividendConstitutentReversedList[i]},Occurs At Decimal Index {i},Place Value {placeValueDividendConstituentReversedListCursoredDigit}")
print(f"## Divisor Constituent Digit Revered List Cursored Digit: {decimalDivisorConstitutentReversedList[j]},Occurs At Decimal Index {j},Place Value {placeValueDivisorConstituentReversedListCursoredDigit}")

print(f"### Division:{division}")
print(f"### Reminder:{reminder}")

print(f"###Division Matrix Row Cursor Index:{twoDimensionalMatrixRowCursorPlaceValue}")
print(f"### Division Matrix Column Cursor Index:{twoDimensionalMatrixColumnCursorPlaceValue}")


divisionMatrix [twoDimensionalMatrixRowCursorPlaceValue][twoDimensionalMatrixColumnCursorPlaceValue] = division
remainderMatrix [twoDimensionalMatrixRowCursorPlaceValue][twoDimensionalMatrixColumnCursorPlaceValue] = reminder

dividentCursoredDigitPlaceValue =10 ** (len(str(placeValueDividendConstituentReversedListCursoredDigit))-1)
divisorCursoredDigitPlaceValue =10 ** (len(str(placeValueDivisorConstituentReversedListCursoredDigit))-1)
valueDecimalFactor = (dividentCursoredDigitPlaceValue/divisorCursoredDigitPlaceValue)

print(f"### Divident Cursored Digit Place Value:{dividentCursoredDigitPlaceValue}")
print(f"### Divisor Cursored Digit Place Value:{divisorCursoredDigitPlaceValue}")
print(f"### Value Cursored Digit Place Value:{valueDecimalFactor}")


print(f"numberOfDigitsInDecimalDividendReveredList:{numberOfDigitsInDecimalDividendReveredList}")

k= i+j-4
print(f"k:{k}")

signFactor = (-1)**abs(k)

print(f"signFactor:{signFactor}")

valueDecimalDividerFactor = signFactor * (10 ** abs(k))
print(f"[*]: valueDecimalDividerFactor:{valueDecimalDividerFactor}")

if i+1 == numberOfDigitsInDecimalDividendReveredList and j == 0:
print(f"i inside:{i}")
print(f"j inside:{j}")
valueMatrix [twoDimensionalMatrixRowCursorPlaceValue][twoDimensionalMatrixColumnCursorPlaceValue] = division * 2 / (valueDecimalDividerFactor*10)
else:
valueMatrix [twoDimensionalMatrixRowCursorPlaceValue][twoDimensionalMatrixColumnCursorPlaceValue] = division / valueDecimalDividerFactor

print(f"Divident Cursored Digit Place Value: {dividentCursoredDigitPlaceValue}")
print(f"Divisor Cursored Digit Place Value: {divisorCursoredDigitPlaceValue}")
#valueMatrix [twoDimensionalMatrixRowCursorPlaceValue][twoDimensionalMatrixColumnCursorPlaceValue] = division * ((10 ** j)/(10 ** i))
print(f"------Iteration Ends------")

valueOfDivision:float = valueOfMatrix(valueMatrix)
print(f"#### Division Matrix:'{divisionMatrix}'")
print(f"#### Value Matrix:'{valueMatrix}'")


print(f"#### Value Of Division:'{valueOfDivision}'")