new sistem

This commit is contained in:
2025-10-27 09:26:34 +05:00
parent 0b23d10f8e
commit dd1fa3f7fc
2 changed files with 355 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
from designer import right_column
import flet as ft
class Button_binary_data(ft.CupertinoButton):
def __init__(self, text: str = "Двоичная система счисления"):
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def test_data(e, self):
md1="""
Двоичная система счисления — это система, в которой используются только две цифры: 0 и 1.
Двои́чная систе́ма счисле́ния — позиционная система счисления с основанием 2. Благодаря непосредственной реализации в цифровых электронных схемах на логических вентилях, двоичная система используется практически во всех современных компьютерах и прочих вычислительных электронных устройствах.
Компьютеры хранят отрицательные числа иначе, чем положительные, из-за особенностей двоичной системы и конструкции процессоров. Вот основные способы:
1. Прямой код (очень редко используется)
Старший бит (самый левый) делает число отрицательным:
Например, для 8 бит:
00010101 — это +21
10010101 — это -21
Недостатки: две разные записи нуля (положительный и отрицательный), сложнее реализовать арифметику.
2. Обратный код (редко используется)
Если число отрицательное, инвертируются все биты, кроме знакового:
+21: 00010101
-21: 11101010
Недостатки: две записи нуля, сложная арифметика.
3. Дополнительный код (почти всегда используется)
Для отрицательного числа инвертируются все биты и прибавляется единица:
+21: 00010101
-21: инвертируем: 11101010, прибавляем 1: 11101011
Преимущества: только одна запись нуля, простая арифметика (сложение и вычитание одинаковы для положительных и отрицательных чисел).
Почему люди пишут числа как "-10101"
Запись -10101 — это просто привычный способ обозначения отрицательных чисел в десятичной или любой другой системе счисления.
В памяти компьютера знак не хранится отдельно, а закодирован в битах (обычно старший бит — знаковый).
Для человека запись с минусом интуитивно понятна, для компьютера — это набор битов, интерпретируемый по правилам (обычно дополнительного кода).
Другие тонкости
Знаковый и беззнаковый типы:
Например, в языке C/C++ есть int (знаковый) и unsigned int (беззнаковый).
Переполнение:
Если сумма двух больших положительных чисел выходит за пределы диапазона типа, возникает переполнение.
Диапазон значений:
В 8 битах:
беззнаковый: 0..255
знаковый (доп. код): -128..127
Пример (8 бит, дополнительный код)
+5: 00000101
-5: инвертируем: 11111010, прибавляем 1: 11111011
Сложение: 00000101 + 11111011 = 00000000 (0), перенос игнорируется
Мантиса, запятая и хранение дробных чисел
Мантиса — это дробная часть числа в позиционной системе. В двоичной мантиса хранится как последовательность битов, где k-й бит дробной части соответствует весу 2^{-k}.
Запятая (разделитель) в человеческом вводе обозначает границу между целой частью и мантиссой. Пример: 101,101₂ = 1*2^2 + 0*2^1 + 1*2^0 + 1*2^{-1} + 0*2^{-2} + 1*2^{-3} = 5.625.
В реальной памяти компьютера точка (запятая) обычно не хранится как символ. Существует два распространённых способа хранения дробных чисел:
- Fixed-point (fixed Q-format): число хранится как целое, представляющее значение scaled = round(x * 2^{f}), где f — количество бит дробной части. Таким образом все числа интерпретируются как scaled/2^{f}.
- Floating-point (IEEE-754): хранится знак, экспонента и мантисса; формат сложнее, даёт большой диапазон и нормализацию.
В этом калькуляторе дроби вводятся через запятую и обрабатываются как обычные дробные значения (float) с фиксированной точностью при выводе (frac_precision бит).
Практические рекомендации
- Если хотите работать с отрицательными целыми в двоичной системе — вводите строку ровно N бит (например, 16). Старший бит будет определять знак.
- Для дробных значений используйте запятую и при необходимости ставьте знак '-' перед всем числом: -101,01.
- Помните про переполнение: при выводе целого результата в двоичной системе он должен помещаться в выбранную разрядность.
"""
right_column.controls=[ ft.Container(
bgcolor="#55257D",
padding=ft.padding.all(10),
border_radius=10,
expand=True,
content=ft.Column(
scroll=ft.ScrollMode.AUTO,
expand=True,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text(md1, size=16, color="white"),
ft.Text("Перевод из десятичной системы в двоичную:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 1.jpg", expand=True),
border_radius=10,
width=350,
height=300,
),
ft.Text("Перевод обратно в десятичную систему:", size=16, color="white"),
ft.Container(
bgcolor="#000000",
content=ft.Image(src="./Система счисления 2.png", expand=True),
border_radius=10,
width=580,
height=300,
),
ft.Text("Работа со знаком:", size=16, color="white"),
],
#width=600,
)
)]
e.page.update()

View File

@@ -0,0 +1,237 @@
from designer import right_column
import flet as ft
class Button_binary_calculator(ft.CupertinoButton):
def __init__(self, text: str = "Двоичный калькулятор"):
self.result_left = ft.Text(value="0", size=30, width=300)
self.result_right = ft.Text(value="0", size=30, width=300)
self.decimal_left = ft.Text(value="(0₁₀)", size=14, color="#B0B0B0", width=300)
self.decimal_right = ft.Text(value="(0₁₀)", size=14, color="#B0B0B0", width=300)
# Поля ввода для вычитания
self.input_left_1 = None
self.input_left_2 = None
# Поля ввода для сложения
self.input_right_1 = None
self.input_right_2 = None
# Количество бит для представления (по умолчанию 8)
self.bit_width = 16
super().__init__(
bgcolor="#00000000",
disabled_bgcolor="#3A1E51",
text=text,
color="white",
on_click=self.test_data
)
def to_twos_complement(self, num, bit_width):
"""Преобразует число в дополнительный код"""
if num >= 0:
return format(num, f'0{bit_width}b')
else:
# Для отрицательных чисел используем дополнительный код
return format((1 << bit_width) + num, f'0{bit_width}b')
def from_twos_complement(self, binary_str):
"""Преобразует из дополнительного кода в десятичное число"""
bit_width = len(binary_str)
value = int(binary_str, 2)
# Проверяем знаковый бит (старший бит)
if binary_str[0] == '1':
# Отрицательное число
value = value - (1 << bit_width)
return value
def validate_binary(self, value):
"""Проверяет, является ли строка корректным двоичным числом"""
if not value:
return True
# Только 0 и 1
return all(c in "01" for c in value)
def calculate_subtraction(self, e):
try:
bin1 = self.input_left_1.value or "0"
bin2 = self.input_left_2.value or "0"
# Проверка корректности двоичных чисел
if not self.validate_binary(bin1) or not self.validate_binary(bin2):
self.result_left.value = "Ошибка: неверный формат"
self.decimal_left.value = ""
self.result_left.update()
self.decimal_left.update()
return
# Преобразуем двоичные числа в десятичные
if len(bin1) > 0 and bin1[0] == '1' and len(bin1) >= 8:
num1 = self.from_twos_complement(bin1)
else:
num1 = int(bin1, 2) if bin1 else 0
if len(bin2) > 0 and bin2[0] == '1' and len(bin2) >= 8:
num2 = self.from_twos_complement(bin2)
else:
num2 = int(bin2, 2) if bin2 else 0
# Вычисляем результат
result = num1 - num2
# Преобразуем обратно в двоичный формат (дополнительный код)
binary_result = self.to_twos_complement(result, self.bit_width)
self.result_left.value = binary_result
self.decimal_left.value = f"({result}₁₀)"
self.result_left.update()
self.decimal_left.update()
except ValueError as ex:
self.result_left.value = "Ошибка"
self.decimal_left.value = str(ex)
self.result_left.update()
self.decimal_left.update()
def calculate_addition(self, e):
try:
bin1 = self.input_right_1.value or "0"
bin2 = self.input_right_2.value or "0"
# Проверка корректности двоичных чисел
if not self.validate_binary(bin1) or not self.validate_binary(bin2):
self.result_right.value = "Ошибка: неверный формат"
self.decimal_right.value = ""
self.result_right.update()
self.decimal_right.update()
return
# Преобразуем двоичные числа в десятичные
# Если введено в дополнительном коде - интерпретируем как дополнительный код
if len(bin1) > 0 and bin1[0] == '1' and len(bin1) >= 8:
num1 = self.from_twos_complement(bin1)
else:
num1 = int(bin1, 2) if bin1 else 0
if len(bin2) > 0 and bin2[0] == '1' and len(bin2) >= 8:
num2 = self.from_twos_complement(bin2)
else:
num2 = int(bin2, 2) if bin2 else 0
# Вычисляем результат
result = num1 + num2
# Преобразуем обратно в двоичный формат (дополнительный код)
binary_result = self.to_twos_complement(result, self.bit_width)
self.result_right.value = binary_result
self.decimal_right.value = f"({result}₁₀)"
self.result_right.update()
self.decimal_right.update()
except ValueError as ex:
self.result_right.value = "Ошибка"
self.decimal_right.value = str(ex)
self.result_right.update()
self.decimal_right.update()
def test_data(self, e):
# Создаем поля ввода с валидацией для двоичных чисел
self.input_left_1 = ft.TextField(
label="Двоичное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"), # только 0 и 1
hint_text="Например: 00001010 (10) или 11110110 (-10)"
)
self.input_left_2 = ft.TextField(
label="Двоичное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"),
hint_text="Например: 00000101 (5)"
)
self.input_right_1 = ft.TextField(
label="Двоичное число 1",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"),
hint_text="Например: 00001010 (10)"
)
self.input_right_2 = ft.TextField(
label="Двоичное число 2",
width=250,
text_align=ft.TextAlign.RIGHT,
value="0",
input_filter=ft.InputFilter(regex_string=r"^[01]*$"),
hint_text="Например: 00000101 (5)"
)
right_column.controls = [ft.Container(
bgcolor="#55257D",
padding=ft.padding.all(10),
border_radius=10,
expand=True,
content=ft.Column(
scroll=ft.ScrollMode.AUTO,
expand=True,
controls=[
ft.Text("Двоичный калькулятор (дополнительный код)", size=20, color="white", weight=ft.FontWeight.BOLD),
ft.Text("Отрицательные числа в дополнительном коде (старший бит = 1)", size=11, color="#B0B0B0", italic=True),
ft.Text(f"Разрядность: {self.bit_width} бит. Диапазон: {-(1 << (self.bit_width-1))} .. {(1 << (self.bit_width-1))-1}", size=11, color="#B0B0B0"),
ft.Row(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
vertical_alignment=ft.CrossAxisAlignment.START,
controls=[
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.input_left_1,
ft.Text("——— Вычитание", size=12, color="white"),
self.input_left_2,
ft.Container(
content=ft.Column([
self.result_left,
self.decimal_left
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_subtraction)
]
),
ft.Column(
expand=True,
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.input_right_1,
ft.Text("—|— Сложение", size=12, color="white"),
self.input_right_2,
ft.Container(
content=ft.Column([
self.result_right,
self.decimal_right
], horizontal_alignment=ft.CrossAxisAlignment.CENTER),
bgcolor="#3A1E51",
padding=10,
border_radius=5,
),
ft.CupertinoButton("=", on_click=self.calculate_addition)
]
)
]
)
],
)
)]
e.page.update()