diff --git a/src/bitutils.py b/src/bitutils.py index aac0044..5a82070 100644 --- a/src/bitutils.py +++ b/src/bitutils.py @@ -74,4 +74,6 @@ def xor(x, y): else: result += '0' - return result + return result + else: + pass diff --git a/src/divide-float.py b/src/divide-float.py new file mode 100644 index 0000000..62315cc --- /dev/null +++ b/src/divide-float.py @@ -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) diff --git a/src/divide.py b/src/divide.py index d56783e..57cfe7d 100644 --- a/src/divide.py +++ b/src/divide.py @@ -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}")