zhangchenyvn 发表于 2024-10-26 19:30:17

0.1+0.2 == 0.3: Ture

# cook your dish here
class HighPrecisionFloat:
    def __init__(self, value, precision=10):
      if isinstance(value, str):
            self.negative = value.startswith('-')
            if self.negative:
                value = value
            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("Unsupported value type")
      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 _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) + int(b_frac) + 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) + int(b_int) + 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):

      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) - int(b_frac) - 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) - int(b_int) - 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 = * (len(a) + len(b))

      for i in range(len(a) - 1, -1, -1):
            for j in range(len(b) - 1, -1, -1):
                result += int(a) * int(b)
                result += result // 10
                result %= 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

      # Preprocessing:
      if self.int_part is None and self.frac_part is None:

            preprocessing_flag = True if preprocessing_flag == False else True

            self.int_part = self.frac_part
            self.frac_part = self.frac_part

            other.int_part = other.frac_part
            other.frac_part = other.frac_part

      precision = self.precision if (
            self.int_part is not None) else (self.precision + 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

# Example usage:


if __name__ == "__main__":
    a = HighPrecisionFloat("0.1")
    b = HighPrecisionFloat("0.2")

    print("Addition:", str(a + b))
    print("Subtraction:", str(a - b))
    print("Multiplication:", str(a * b))
    print("Division:", str(a / b))

    print(a, b)

FishC 发表于 2024-10-26 19:30:32

这段代码定义了一个 `HighPrecisionFloat` 类,用于进行高精度浮点数运算。以下是修复代码中未完成部分的要点:

1. **完成 `_add_abs` 方法:**

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) + int(b_frac) + carry
      carry = sum_val // 10
      frac_sum.append(str(sum_val % 10))

    frac_sum.reverse()
    frac_sum = ''.join(frac_sum).rstrip('0') or '0'

    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) + int(b_int) + 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).lstrip('0') or '0'

    return int_sum, frac_sum

2. **完成 `_sub_abs` 方法:**

def _sub_abs(self, other):
    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) - int(b_frac) - 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) - int(b_int) - 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

3. **调整 `_mul_abs` 和 `_div_abs` 方法:**

这两个方法的实现可能较复杂,需要具体的逐位乘法和长除法逻辑,考虑选择使用Python内置的 `decimal.Decimal` 进行运算以保持简单和精确。

这样完整性和基本功能可以确保正常,下面继续执行代码即可:
if __name__ == "__main__":
    a = HighPrecisionFloat("0.1")
    b = HighPrecisionFloat("0.2")

    print("Addition:", str(a + b))
    print("Subtraction:", str(a - b))
    print("Multiplication:", str(a * b))
    print("Division:", str(a / b))

确保这些方法在实现时都能匹配实际运算需求。如果希望简化实现,尤其是更复杂的乘法和除法,可以考虑针对特定情况下的改进。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zhangchenyvn 发表于 2024-10-26 19:33:45

我就是因为很讨厌decimal库才写的

FishC 发表于 2024-10-26 19:33:59

zhangchenyvn 发表于 2024-10-26 19:33
我就是因为很讨厌decimal库才写的

看得出来,您是为了避免使用 `decimal` 库而做了手动实现。这里的确需要进一步完善代码中几个地方以确保加减乘除都能正确执行。下面是一些改进建议:

### 1. 完成 `_add_abs` 方法:
将 `int_sum` 和 `frac_sum` 的列表初始化补齐。

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) + int(b_frac) + carry
      carry = sum_val // 10
      frac_sum.append(str(sum_val % 10))

    frac_sum.reverse()
    frac_sum = ''.join(frac_sum).rstrip('0') or '0'

    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) + int(b_int) + 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).lstrip('0') or '0'

    return int_sum, frac_sum

### 2. 完成 `_sub_abs` 方法:

def _sub_abs(self, other):
    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) - int(b_frac) - 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) - int(b_int) - 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

### 3. 乘法和除法实现:

乘法和除法操作较为复杂,尤其是在处理不同长度的小数时。可以通过移位技巧处理。

对于除法,建议使用逐位除法算法,可考虑用高精度整数进行分割,再结合小数部分。

完成以上改动后,可以逐步运行测试,以确保各数学运算的正确性。由于手写浮点数运算相对复杂,建议从简单的加减运算开始调试,再延伸到乘除处理。如果您有具体问题或测试用例,可以继续探讨。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

简柠啦 发表于 2024-10-27 09:10:19

{:10_256:}{:10_256:}

菜菜大大^_^ 发表于 2024-10-27 13:11:12

卧槽这是{:10_243:}

zhangchenyvn 发表于 2024-10-27 19:09:29

菜菜大大^_^ 发表于 2024-10-27 13:11
卧槽这是

手写加减{:10_256:}

很cool的阳 发表于 2024-10-28 09:07:21

{:7_113:}

trinityee 发表于 2024-10-28 10:37:28

{:10_254:}{:10_254:}

OKMY 发表于 2024-10-30 19:07:48

快速收敛 发表于 2024-11-12 10:01:07

{:10_279:}
页: [1]
查看完整版本: 0.1+0.2 == 0.3: Ture