## /utils/component/numbers/big_number.py
__all__ = [
'BigNumber',
]
[документация]
class BigNumber:
"""
Представление большого числа с автоматическим управлением масштабом.
"""
__slots__ = ('value')
scales_list: list[tuple[str, float]] = [
('', 1),
('K', 1e3),
('M', 1e6),
('B', 1e9),
('T', 1e12),
('Qd', 1e15),
('Qn', 1e18),
('Sx', 1e21),
('Sp', 1e24),
('Oc', 1e27),
('No', 1e30),
('De', 1e33),
('UDe', 1e36),
('DDe', 1e39),
('TDe', 1e42),
('Vg', 1e45),
('Tg', 1e48),
('Qa', 1e51),
('Qi', 1e54),
('Se', 1e57),
('Sg', 1e60),
('Og', 1e63),
('Ng', 1e66),
('Ce', 1e69),
('UCe', 1e72),
('DCe', 1e75),
('TCe', 1e78),
('DC', 1e81),
('TC', 1e84),
('QdC', 1e87),
('QnC', 1e90),
('SxC', 1e93),
('SpC', 1e96),
('OcC', 1e99),
('NoC', 1e102),
('Mi', 1e105),
('Mi-M', 1e108),
('Mi-B', 1e111),
('Mi-T', 1e114),
('DMi', 1e117),
('TMi', 1e120),
('DeMi', 1e123),
('VgMi', 1e126),
('TgMi', 1e129),
('CeMi', 1e132),
('DCeMi', 1e135),
('TCeMi', 1e138),
('Mc', 1e141),
('Na', 1e144),
('Pi', 1e147),
('Fe', 1e150),
('At', 1e153),
('Ze', 1e156),
('Yo', 1e159),
('Xo', 1e162),
('Ve', 1e165),
]
scales_dict: dict[str, float] = {label: factor for label, factor in scales_list}
def __init__(self, value: int | float, scale: str = '') -> None:
"""
Создает экземпляр, преобразуя значение из указанной шкалы в базовую.
:param value: Числовое значение
:param scale: Обозначение масштаба ('K', 'M', 'B' и т.д.)
:raises TypeError: Если значение не int или float
:raises TypeError: Если scale не строка
"""
if not isinstance(value, (int, float)):
raise TypeError("Value must be int or float")
if not isinstance(scale, str):
raise TypeError("Scale must be a string")
scale = scale.strip().upper()
factor = self.scales_dict.get(scale, 1)
self.value: float = float(value) * factor
[документация]
def to_scale_string(self, precision: int = 2) -> str:
"""
Возвращает строку с числом, автоматически масштабированным, например: '1.23 M'.
:param precision: Число знаков после запятой
:return: Строка с маштабированным числом.
"""
abs_value: float = abs(self.value)
for label, factor in reversed(self.scales_list):
if abs_value >= factor:
display_value: float = self.value / factor
return f"{display_value:.{precision}f} {label}".strip()
return f"{self.value:.{precision}f}"
[документация]
def to_scientific(self, precision: int = 2) -> str:
"""
Возвращает число в научной нотации, например: '1.23e+06'.
:param precision: Число знаков после запятой
:return: Строка с числом в научной нотации.
"""
return f"{self.value:.{precision}e}"
[документация]
def convert_to_scale(self, target_scale: str) -> 'BigNumber':
"""
Преобразует число в указанную шкалу, например: миллионы в тысячи.
:param target_scale: Целевое обозначение масштаба
:return: Масштобированное значение.
:raises ValueError: Если масштаб неподдерживаем
"""
if target_scale not in self.scales_dict:
raise ValueError(f"Unsupported scale: {target_scale}") # — на английском
target_factor: float = self.scales_dict[target_scale]
new_value: float = self.value / target_factor
return BigNumber(new_value, target_scale)
def __pow__(self, power: int | float) -> 'BigNumber':
"""
Возводит число в степень.
:param power: Степень.
:return: Измененное число.
"""
return BigNumber(self.value ** power)
def __add__(self, other: 'BigNumber | int | float') -> 'BigNumber':
"""
Складывает два объекта или число.
:param other: Значение для операции.
:return: Измененное число.
"""
if isinstance(other, BigNumber):
return BigNumber(self.value + other.value)
else:
return BigNumber(self.value + other)
def __sub__(self, other: 'BigNumber | int | float') -> 'BigNumber':
"""
Вычитает из этого число или объект BigNumber.
:param other: Значение для операции.
:return: Измененное число.
"""
if isinstance(other, BigNumber):
return BigNumber(self.value - other.value)
else:
return BigNumber(self.value - other)
def __mul__(self, other: 'BigNumber | int | float') -> 'BigNumber':
"""
Умножает на объект BigNumber или число.
:param other: Значение для операции.
:return: Измененное число.
"""
if isinstance(other, BigNumber):
return BigNumber(self.value * other.value)
else:
return BigNumber(self.value * other)
def __truediv__(self, other: 'BigNumber | int | float') -> 'BigNumber':
"""
Делит это число или объект BigNumber на другое число.
:param other: Значение для операции.
:return: Измененное число.
"""
if isinstance(other, BigNumber):
return BigNumber(self.value / other.value)
else:
return BigNumber(self.value / other)
def __str__(self) -> str:
"""
Строковое представление, автоматически масштабируемое.
:return: Представление числа в виде строки.
"""
return self.to_scale_string()
def __repr__(self) -> str:
"""
Формальное строковое представление для отладки.
:return: Представление числа в виде строки.
"""
return f"BigNumber(value={self.value:.2f})"