"""
_____ _ _ ____ _____
|__ / | | | | _ \| ___|
/ / _____ | |_| | |_) | |_
/ /_ |_____| | _ | __/| _|
/____| |_| |_|_| |_|
@file HPF.py
@info Pure self-defined High Precision Float Platfrom
@auth Chenyun Z.
@auth hi-zcy.com, dev.to/chenyun
@create Oct. 27 2024
@license MIT License
@WARN Do NOT edit infomation above this!
@edit Oct. 27 2024
"""
class HighPrecisionFloat:
def __init__(self, value, precision=10):
if isinstance(value, str):
self.negative = value.startswith('-')
if self.negative:
value = value[1:]
if '.' in value:
self.int_part, self.frac_part = value.split('.')
else:
self.int_part, self.frac_part = value, '0'
elif isinstance(value, (int, float)):
self.negative = value < 0
value = str(abs(value))
if '.' in value:
self.int_part, self.frac_part = value.split('.')
else:
self.int_part, self.frac_part = value, '0'
else:
raise ValueError(f"Unsupported value type: {type(value)}.")
self.int_part = self.int_part.lstrip('0') or '0'
self.frac_part = self.frac_part.rstrip('0') or '0'
self.precision = precision
def __str__(self):
sign = '-' if self.negative else ''
if int(self.frac_part):
return f"{sign}{self.int_part}.{self.frac_part}"
else:
return f"{sign}{self.int_part}"
def __repr__(self):
return f"HighPrecisionFloat('{str(self)}')"
def _align_parts(self, other):
max_frac_len = max(len(self.frac_part), len(other.frac_part))
self_frac = self.frac_part.ljust(max_frac_len, '0')
other_frac = other.frac_part.ljust(max_frac_len, '0')
return self.int_part, self_frac, other.int_part, other_frac
def __add__(self, other):
if not isinstance(other, HighPrecisionFloat):
other = HighPrecisionFloat(other)
if self.negative == other.negative:
int_part, frac_part = self._add_abs(other)
result = HighPrecisionFloat(f"{int_part}.{frac_part}")
result.negative = self.negative
else:
if self._abs_greater(other):
int_part, frac_part = self._sub_abs(other)
result = HighPrecisionFloat(f"{int_part}.{frac_part}")
result.negative = self.negative
else:
int_part, frac_part = other._sub_abs(self)
result = HighPrecisionFloat(f"{int_part}.{frac_part}")
result.negative = other.negative
return result
def __sub__(self, other):
if not isinstance(other, HighPrecisionFloat):
other = HighPrecisionFloat(other)
other.negative = not other.negative
result = self + other
other.negative = not other.negative
return result
def __mul__(self, other):
if not isinstance(other, HighPrecisionFloat):
other = HighPrecisionFloat(other)
int_part, frac_part = self._mul_abs(other)
result = HighPrecisionFloat(f"{int_part}.{frac_part}")
result.negative = self.negative != other.negative
return result
def __truediv__(self, other):
if not isinstance(other, HighPrecisionFloat):
other = HighPrecisionFloat(other)
int_part, frac_part = self._div_abs(other)
result = HighPrecisionFloat(f"{int_part}.{frac_part}")
result.negative = self.negative != other.negative
return result
def __floordiv__(self, other):
return HighPrecisionFloat(self.__truediv__(other).int_part)
def __del__(self):
del self.frac_part
del self.int_part
del self.precision
def _add_abs(self, other):
a_int, a_frac, b_int, b_frac = self._align_parts(other)
carry = 0
frac_sum = []
for i in range(len(a_frac) - 1, -1, -1):
sum_val = int(a_frac[i]) + int(b_frac[i]) + carry
carry = sum_val // 10
frac_sum.append(str(sum_val % 10))
frac_sum.reverse()
frac_sum = ''.join(frac_sum)
int_sum = []
a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), \
b_int.zfill(max(len(a_int), len(b_int)))
for i in range(len(a_int) - 1, -1, -1):
sum_val = int(a_int[i]) + int(b_int[i]) + carry
carry = sum_val // 10
int_sum.append(str(sum_val % 10))
if carry:
int_sum.append(str(carry))
int_sum.reverse()
int_sum = ''.join(int_sum)
return int_sum, frac_sum
def _sub_abs(self, other):
"""
This isn't a useful function.
The method __sub__ used the function "_add_abs".
"""
a_int, a_frac, b_int, b_frac = self._align_parts(other)
borrow = 0
frac_diff = []
for i in range(len(a_frac) - 1, -1, -1):
diff = int(a_frac[i]) - int(b_frac[i]) - borrow
if diff < 0:
diff += 10
borrow = 1
else:
borrow = 0
frac_diff.append(str(diff))
frac_diff.reverse()
frac_diff = ''.join(frac_diff).rstrip('0') or '0'
int_diff = []
a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), \
b_int.zfill(max(len(a_int), len(b_int)))
for i in range(len(a_int) - 1, -1, -1):
diff = int(a_int[i]) - int(b_int[i]) - borrow
if diff < 0:
diff += 10
borrow = 1
else:
borrow = 0
int_diff.append(str(diff))
int_diff.reverse()
int_diff = ''.join(int_diff).lstrip('0') or '0'
return int_diff, frac_diff
def _mul_abs(self, other):
a = self.int_part + self.frac_part
b = other.int_part + other.frac_part
self_frac_len = len(self.frac_part.strip('0'))
other_frac_len = len(other.frac_part.strip('0'))
total_frac_len = self_frac_len + other_frac_len
a_len, b_len = len(self.frac_part), len(other.frac_part)
result = [0] * (len(a) + len(b))
for i in range(len(a) - 1, -1, -1):
for j in range(len(b) - 1, -1, -1):
result[i + j + 1] += int(a[i]) * int(b[j])
result[i + j] += result[i + j + 1] // 10
result[i + j + 1] %= 10
result = ''.join(map(str, result)).lstrip('0') or '0'
# print(result)
int_part = result[:-a_len - b_len] or '0'
frac_part = result[-a_len - b_len:] or '0'
frac_part = frac_part.zfill(total_frac_len)
return int_part, frac_part
def _div_abs(self, other):
preprocessing_flag = False
pre_count = float(self.int_part + '.' + self.frac_part ) \
/ float(other.int_part + '.' + other.frac_part)
precision = self.precision + len(str(pre_count))
# Preprocessing:
if self.int_part is None and self.frac_part is None:
preprocessing_flag = True
self.int_part = self.frac_part[0]
self.frac_part = self.frac_part[1:]
other.int_part = other.frac_part[0]
other.frac_part = other.frac_part[1:]
a = self.int_part + self.frac_part
b = other.int_part + other.frac_part
self_frac_len = len(self.frac_part.strip('0'))
other_frac_len = len(other.frac_part.strip('0'))
total_frac_len = self_frac_len + other_frac_len
a_len, b_len = len(self.frac_part), len(other.frac_part)
a = a.ljust(len(a) + precision, '0')
result = []
remainder = 0
for digit in a:
remainder = remainder * 10 + int(digit)
result.append(str(remainder // int(b)))
remainder %= int(b)
result = ''.join(result).lstrip('0') or '0'
# print(result)
int_part = (
result[:-precision -1]
if (
(self.int_part is None)
or
(other.int_part is None)
)
else result[:-precision]
) or '0'
# print(int_part)
frac_part = result[-precision:] or '0'
if preprocessing_flag:
self.frac_part = "".join(
[
self.int_part,
self.frac_part
]
)
self.int_part = None
other.frac_part = "".join(
[
other.int_part,
other.frac_part
]
)
other.int_part = None
return int_part, frac_part
def _abs_greater(self, other):
if len(self.int_part) != len(other.int_part):
return len(self.int_part) > len(other.int_part)
if self.int_part != other.int_part:
return self.int_part > other.int_part
return self.frac_part > other.frac_part
def pos(self):
pass
def neg(self):
self.negative = False if self.negative else True
def __eq__(self, other):
if not isinstance(other, HighPrecisionFloat):
other = HighPrecisionFloat(other)
return (self.int_part, self.frac_part) == (other.int_part, other.frac_part) and self.negative == other.negative
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if not isinstance(other, HighPrecisionFloat):
other = HighPrecisionFloat(other)
if self.negative != other.negative:
return self.negative
if self.negative:
return not self.__gt__(other)
return self._compare(other) < 0
def __le__(self, other):
return self < other or self == other
def __gt__(self, other):
if not isinstance(other, HighPrecisionFloat):
other = HighPrecisionFloat(other)
if self.negative != other.negative:
return not self.negative
if self.negative:
return not self.__lt__(other)
return self._compare(other) > 0
def __ge__(self, other):
return self > other or self == other
def _compare(self, other):
a_int, a_frac, b_int, b_frac = self._align_parts(other)
# 比较整数部分
if a_int != b_int:
return (a_int > b_int) - (a_int < b_int)
# 整数部分相同,比较小数部分
for ai, bi in zip(a_frac, b_frac):
if ai != bi:
return (ai > bi) - (ai < bi)
# 如果所有位都相同,则相等
return 0
Ähnliche Beiträge
Auch interessante Nachrichten Something about BIGINT in Python:
Thematisch verwandte Begriffe: Something, about, BIGINT, Python · 6 Treffer
🚨 Typosquatting packages on PyPI are targeting 𝗿𝗲𝗾𝘂𝗲𝘀𝘁𝘀, one of the most widely used Python packages. Catch them before compromise.
Proofpoint Brings OpenAI GPT Cyber Models into Security Operations to Help Defenders Investigate Threats Faster
Learn Vectorized Thinking in Python Through Examples
Tengu, a Mirai-style Linux and IoT botnet
Managing Small Context Windows in Language Models
[webapps] Bludit CMS - Stored XSS
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
Beiträge werden geladen ...
Videos werden geladen ...
SOCIAL SHARE CARD GENERATOR