add testing version of divide-float.py - a wrapper which adds support for floating-point division based on existing division methods
This commit is contained in:
parent
3598eb13f1
commit
6018537352
|
@ -75,3 +75,5 @@ def xor(x, y):
|
|||
result += '0'
|
||||
|
||||
return result
|
||||
else:
|
||||
pass
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
# a wrapper for division script which adds support for floating point numbers
|
||||
|
||||
from lib.prettytable import PrettyTable
|
||||
from divide import divide, table_to_text
|
||||
import bitutils as bu
|
||||
|
||||
def get_reference_register_size(*numbers):
|
||||
return max(map(len, numbers))
|
||||
|
||||
def parse_float(number):
|
||||
split_by_dot = number.split('.')
|
||||
Sn = split_by_dot[0] # sign
|
||||
|
||||
split_by_comma = split_by_dot[1].split(',')
|
||||
Pn = len(split_by_comma[0].lstrip('0'))
|
||||
Mn = ''.join(split_by_comma).lstrip('0')
|
||||
|
||||
return Sn, Pn, Mn
|
||||
|
||||
def to_int(number):
|
||||
return int("0b" + number, 2)
|
||||
|
||||
def normalize_mantice(m, n):
|
||||
M_norm = m.lstrip('0')
|
||||
P_delta = len(m) - len(M_norm)
|
||||
|
||||
print(f"Normalize: {m} -> {M_norm} (shifted right {P_delta} times)")
|
||||
|
||||
return M_norm[:n], P_delta
|
||||
|
||||
def round_mantice(m, n):
|
||||
closest_upper = bu.sum(m[:n+1], '1', n+1)
|
||||
return closest_upper[:n]
|
||||
|
||||
def print_classic_float(label, Sn, Pn, Mn):
|
||||
pt = PrettyTable()
|
||||
pt.field_names = [f"S{label}", f"P{label}", f"M{label}"]
|
||||
pt.add_row([Sn, bin(Pn).lstrip('-')[2:], Mn])
|
||||
print(pt)
|
||||
|
||||
def print_shortened_float(label, Sn, Pn, Mn):
|
||||
mutable_mantice = list(Mn)
|
||||
P = Pn
|
||||
while P < 0:
|
||||
mutable_mantice.insert(0, '0')
|
||||
P += 1
|
||||
|
||||
if P > len(mutable_mantice):
|
||||
for i in range(len(mutable_mantice), P+1):
|
||||
mutable_mantice.insert(i, '0')
|
||||
mutable_mantice.insert(P, ',')
|
||||
result_string = ''.join(mutable_mantice)
|
||||
print(f"{Sn}.{result_string}".replace(".,", ".0,"))
|
||||
|
||||
def divide_float(x, y, method, n = 0, verbose = False):
|
||||
Sx, Px, Mx = parse_float(x)
|
||||
Sy, Py, My = parse_float(y)
|
||||
|
||||
print(f"Число X:\n" \
|
||||
f"Знак мантиси: {Sx}\n" \
|
||||
f"Порядок: {Px}\n" \
|
||||
f"Мантиса: {Mx}\n")
|
||||
|
||||
print(f"Число Y:\n" \
|
||||
f"Знак мантиси: {Sy}\n" \
|
||||
f"Порядок: {Py}\n" \
|
||||
f"Мантиса: {My}")
|
||||
|
||||
'''
|
||||
while to_int(Mx) >= to_int(My):
|
||||
print(f"Mx >= My ({Mx} >= {My}), тому зсуваємо Mx на один розряд праворуч і збільшуємо порядок числа X")
|
||||
Mx = '0' + Mx
|
||||
Px += 1
|
||||
'''
|
||||
|
||||
Mx = Mx.rstrip("0")
|
||||
My = My.rstrip("0")
|
||||
|
||||
print("Запис чисел у класичному форматі:")
|
||||
print_classic_float('x', Sx, Px, Mx)
|
||||
print()
|
||||
print_classic_float('y', Sy, Py, My)
|
||||
print()
|
||||
|
||||
#reg_size = get_reference_register_size(Mx, My)
|
||||
|
||||
while to_int(Mx) >= to_int(My):
|
||||
print(f"Mx >= My ({Mx} >= {My}), тому зсуваємо Mx на один розряд праворуч і збільшуємо порядок числа X")
|
||||
Mx = '0' + Mx
|
||||
My = My + '0'
|
||||
Px += 1
|
||||
|
||||
if n == 0:
|
||||
reg_size = get_reference_register_size(Mx, My)
|
||||
print(f"n = 0, отже довжина регістрів обирається автоматично ({reg_size})")
|
||||
else:
|
||||
reg_size = n
|
||||
|
||||
table, result = divide(reg_size, to_int(bu.al(Mx, reg_size)), to_int(bu.al(My, reg_size)), method)
|
||||
print(f"Процес ділення методом #{method}:\n{table_to_text(table)}\n")
|
||||
|
||||
print("Маємо результат:")
|
||||
|
||||
S_result = bu.xor(Sx, Sy)
|
||||
print(f"Знаковий розряд: {Sx} ⊕ {Sy} = {S_result}")
|
||||
|
||||
M_norm, P_delta = normalize_mantice(result, n+1)
|
||||
print(f"Нормалізована мантиса: ,{M_norm}")
|
||||
|
||||
P_result = Px - Py - P_delta
|
||||
print(f"Порядок: {Px} + {Py} - {P_delta} = {P_result}")
|
||||
|
||||
M_result = round_mantice(bu.al(result, n+1), n+1)
|
||||
print(f"Округлюємо мантису до {reg_size} розрядів: ,{M_result}")
|
||||
|
||||
return S_result, P_result, M_result
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_x = input("X: ")
|
||||
start_y = input("Y: ")
|
||||
n = int(input("n: "))
|
||||
method = int(input("Method: "))
|
||||
|
||||
S_result, P_result, M_result = divide_float(start_x, start_y, method, n)
|
||||
|
||||
print(f"Запишемо результат у вигляді таблиці:")
|
||||
print_classic_float('f', S_result, P_result, M_result)
|
||||
print("І отримуємо остаточне число після ділення:")
|
||||
print_shortened_float('F', S_result, P_result, M_result)
|
|
@ -3,16 +3,16 @@ import bitutils as bu
|
|||
def divide(n, int_x, int_y, method):
|
||||
if method == 1:
|
||||
# getting binary values
|
||||
x = bu.ar(bin(int_x)[2:], n)
|
||||
y = bu.ar(bin(int_y)[2:], n)
|
||||
x = bu.ar(bin(int_x)[2:], n+2)
|
||||
y = bu.ar(bin(int_y)[2:], n+2)
|
||||
|
||||
# getting the supplementary code of X
|
||||
y_inv = "".join([bu.inv(i) for i in y]) # invert
|
||||
y_inv = bu.sum(y_inv, '1', n) # +1
|
||||
y_inv = bu.sum(y_inv, '1', n+2) # +1
|
||||
|
||||
# writing startup register values
|
||||
# registers order: RG3, RG2, RG1
|
||||
rg_table = [[['start', '1'*(n-1), x, y, '-'], ['start', '1'*(n-1), x, y_inv, '-']]]
|
||||
rg_table = [[['start', '1'*(n+1), x, y, '-'], ['start', '1'*(n+1), x, y_inv, '-']]]
|
||||
|
||||
# iterations counter
|
||||
i = 0
|
||||
|
@ -25,7 +25,7 @@ def divide(n, int_x, int_y, method):
|
|||
rg_table[-1].append([
|
||||
i,
|
||||
rg_table[-2][-1][1], # copy previous value
|
||||
bu.sum(rg_table[-2][-1][2], rg_table[0][0][3], n), # RG2 := RG2 + RG1
|
||||
bu.sum(rg_table[-2][-1][2], rg_table[0][0][3], n+2), # RG2 := RG2 + RG1
|
||||
'-',
|
||||
"RG2 := RG2 + RG1"
|
||||
])
|
||||
|
@ -33,7 +33,7 @@ def divide(n, int_x, int_y, method):
|
|||
rg_table[-1].append([
|
||||
i,
|
||||
rg_table[-2][-1][1], # copy previous value
|
||||
bu.sum(rg_table[-2][-1][2], rg_table[0][1][3], n), # RG2 := RG2 - RG1
|
||||
bu.sum(rg_table[-2][-1][2], rg_table[0][1][3], n+2), # RG2 := RG2 - RG1
|
||||
'-',
|
||||
"RG2 := RG2 - RG1"
|
||||
])
|
||||
|
@ -104,11 +104,29 @@ def divide(n, int_x, int_y, method):
|
|||
return rg_table, rg_table[-1][-1][1][1:]
|
||||
|
||||
|
||||
def table_to_text(dt):
|
||||
from lib.prettytable import PrettyTable
|
||||
pt = PrettyTable()
|
||||
pt.field_names = ["Iteration", "RG3", "RG2", "RG1", "Operations"]
|
||||
|
||||
for i in dt:
|
||||
for j in range(len(i)):
|
||||
if j+1 == len(i):
|
||||
pt.add_row(i[j], divider = True)
|
||||
else:
|
||||
pt.add_row(i[j])
|
||||
|
||||
return pt.get_string()
|
||||
|
||||
if __name__ == "__main__":
|
||||
# a fully functional reference
|
||||
# implementation for this library
|
||||
# is provided below
|
||||
|
||||
# usage change of method #1
|
||||
print("УВАГА! Для першого методу додавати два нулі перед числом БІЛЬШЕ НЕ ПОТРІБНО!\n"
|
||||
"(це попередження буде прибрано у майбутніх версіях, вводьте числа уважно)")
|
||||
|
||||
raw_x = input("X: ")
|
||||
raw_y = input("Y: ")
|
||||
|
||||
|
@ -124,16 +142,5 @@ if __name__ == "__main__":
|
|||
|
||||
dt, result = divide(n, x, y, method)
|
||||
|
||||
from lib.prettytable import PrettyTable
|
||||
pt = PrettyTable()
|
||||
pt.field_names = ["Iteration", "RG3", "RG2", "RG1", "Operations"]
|
||||
|
||||
for i in dt:
|
||||
for j in range(len(i)):
|
||||
if j+1 == len(i):
|
||||
pt.add_row(i[j], divider = True)
|
||||
else:
|
||||
pt.add_row(i[j])
|
||||
|
||||
print(pt)
|
||||
print(table_to_text(dt))
|
||||
print(f"Result: {result}")
|
||||
|
|
Loading…
Reference in New Issue