鱼C论坛

 找回密码
 立即注册
查看: 616|回复: 11

[作品展示] 0.1+0.2 == 0.3: Ture

[复制链接]
发表于 2024-10-26 19:30:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. # cook your dish here
  2. class HighPrecisionFloat:
  3.     def __init__(self, value, precision=10):
  4.         if isinstance(value, str):
  5.             self.negative = value.startswith('-')
  6.             if self.negative:
  7.                 value = value[1:]
  8.             if '.' in value:
  9.                 self.int_part, self.frac_part = value.split('.')
  10.             else:
  11.                 self.int_part, self.frac_part = value, '0'
  12.         elif isinstance(value, (int, float)):
  13.             self.negative = value < 0
  14.             value = str(abs(value))
  15.             if '.' in value:
  16.                 self.int_part, self.frac_part = value.split('.')
  17.             else:
  18.                 self.int_part, self.frac_part = value, '0'
  19.         else:
  20.             raise ValueError("Unsupported value type")
  21.         self.int_part = self.int_part.lstrip('0') or '0'
  22.         self.frac_part = self.frac_part.rstrip('0') or '0'

  23.         self.precision = precision

  24.     def __str__(self):
  25.         sign = '-' if self.negative else ''
  26.         if int(self.frac_part):
  27.             return f"{sign}{self.int_part}.{self.frac_part}"
  28.         else:
  29.             return f"{sign}{self.int_part}"

  30.     def __repr__(self):
  31.         return f"HighPrecisionFloat('{str(self)}')"

  32.     def _align_parts(self, other):
  33.         max_frac_len = max(len(self.frac_part), len(other.frac_part))
  34.         self_frac = self.frac_part.ljust(max_frac_len, '0')
  35.         other_frac = other.frac_part.ljust(max_frac_len, '0')
  36.         return self.int_part, self_frac, other.int_part, other_frac

  37.     def __add__(self, other):
  38.         if not isinstance(other, HighPrecisionFloat):
  39.             other = HighPrecisionFloat(other)
  40.         if self.negative == other.negative:
  41.             int_part, frac_part = self._add_abs(other)
  42.             result = HighPrecisionFloat(f"{int_part}.{frac_part}")
  43.             result.negative = self.negative
  44.         else:
  45.             if self._abs_greater(other):
  46.                 int_part, frac_part = self._sub_abs(other)
  47.                 result = HighPrecisionFloat(f"{int_part}.{frac_part}")
  48.                 result.negative = self.negative
  49.             else:
  50.                 int_part, frac_part = other._sub_abs(self)
  51.                 result = HighPrecisionFloat(f"{int_part}.{frac_part}")
  52.                 result.negative = other.negative
  53.         return result

  54.     def __sub__(self, other):
  55.         if not isinstance(other, HighPrecisionFloat):
  56.             other = HighPrecisionFloat(other)
  57.         other.negative = not other.negative
  58.         result = self + other
  59.         other.negative = not other.negative
  60.         return result

  61.     def __mul__(self, other):
  62.         if not isinstance(other, HighPrecisionFloat):
  63.             other = HighPrecisionFloat(other)
  64.         int_part, frac_part = self._mul_abs(other)
  65.         result = HighPrecisionFloat(f"{int_part}.{frac_part}")
  66.         result.negative = self.negative != other.negative
  67.         return result

  68.     def __truediv__(self, other):
  69.         if not isinstance(other, HighPrecisionFloat):
  70.             other = HighPrecisionFloat(other)
  71.         int_part, frac_part = self._div_abs(other)
  72.         result = HighPrecisionFloat(f"{int_part}.{frac_part}")
  73.         result.negative = self.negative != other.negative
  74.         return result

  75.     def __floordiv__(self, other):
  76.         return HighPrecisionFloat(self.__truediv__(other).int_part)

  77.     def _add_abs(self, other):

  78.         a_int, a_frac, b_int, b_frac = self._align_parts(other)
  79.         carry = 0
  80.         frac_sum = []

  81.         for i in range(len(a_frac) - 1, -1, -1):
  82.             sum_val = int(a_frac[i]) + int(b_frac[i]) + carry
  83.             carry = sum_val // 10
  84.             frac_sum.append(str(sum_val % 10))

  85.         frac_sum.reverse()
  86.         frac_sum = ''.join(frac_sum)

  87.         int_sum = []

  88.         a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), \
  89.             b_int.zfill(max(len(a_int), len(b_int)))

  90.         for i in range(len(a_int) - 1, -1, -1):
  91.             sum_val = int(a_int[i]) + int(b_int[i]) + carry
  92.             carry = sum_val // 10
  93.             int_sum.append(str(sum_val % 10))

  94.         if carry:
  95.             int_sum.append(str(carry))

  96.         int_sum.reverse()
  97.         int_sum = ''.join(int_sum)

  98.         return int_sum, frac_sum

  99.     def _sub_abs(self, other):

  100.         a_int, a_frac, b_int, b_frac = self._align_parts(other)
  101.         borrow = 0
  102.         frac_diff = []

  103.         for i in range(len(a_frac) - 1, -1, -1):
  104.             diff = int(a_frac[i]) - int(b_frac[i]) - borrow
  105.             if diff < 0:
  106.                 diff += 10
  107.                 borrow = 1
  108.             else:
  109.                 borrow = 0
  110.             frac_diff.append(str(diff))

  111.         frac_diff.reverse()
  112.         frac_diff = ''.join(frac_diff).rstrip('0') or '0'

  113.         int_diff = []
  114.         a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), \
  115.             b_int.zfill(max(len(a_int), len(b_int)))

  116.         for i in range(len(a_int) - 1, -1, -1):
  117.             diff = int(a_int[i]) - int(b_int[i]) - borrow
  118.             if diff < 0:
  119.                 diff += 10
  120.                 borrow = 1
  121.             else:
  122.                 borrow = 0
  123.             int_diff.append(str(diff))

  124.         int_diff.reverse()
  125.         int_diff = ''.join(int_diff).lstrip('0') or '0'

  126.         return int_diff, frac_diff

  127.     def _mul_abs(self, other):

  128.         a = self.int_part + self.frac_part
  129.         b = other.int_part + other.frac_part

  130.         self_frac_len = len(self.frac_part.strip('0'))
  131.         other_frac_len = len(other.frac_part.strip('0'))
  132.         total_frac_len = self_frac_len + other_frac_len

  133.         a_len, b_len = len(self.frac_part), len(other.frac_part)
  134.         result = [0] * (len(a) + len(b))

  135.         for i in range(len(a) - 1, -1, -1):
  136.             for j in range(len(b) - 1, -1, -1):
  137.                 result[i + j + 1] += int(a[i]) * int(b[j])
  138.                 result[i + j] += result[i + j + 1] // 10
  139.                 result[i + j + 1] %= 10

  140.         result = ''.join(map(str, result)).lstrip('0') or '0'
  141.         # print(result)
  142.         int_part = result[:-a_len - b_len] or '0'
  143.         frac_part = result[-a_len - b_len:] or '0'

  144.         frac_part = frac_part.zfill(total_frac_len)

  145.         return int_part, frac_part

  146.     def _div_abs(self, other):

  147.         preprocessing_flag = False

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

  150.             preprocessing_flag = True if preprocessing_flag == False else True

  151.             self.int_part = self.frac_part[0]
  152.             self.frac_part = self.frac_part[1:]

  153.             other.int_part = other.frac_part[0]
  154.             other.frac_part = other.frac_part[1:]

  155.         precision = self.precision if (
  156.             self.int_part is not None) else (self.precision + 1)

  157.         a = self.int_part + self.frac_part
  158.         b = other.int_part + other.frac_part

  159.         self_frac_len = len(self.frac_part.strip('0'))
  160.         other_frac_len = len(other.frac_part.strip('0'))
  161.         total_frac_len = self_frac_len + other_frac_len

  162.         a_len, b_len = len(self.frac_part), len(other.frac_part)
  163.         a = a.ljust(len(a) + precision, '0')

  164.         result = []
  165.         remainder = 0

  166.         for digit in a:
  167.             remainder = remainder * 10 + int(digit)
  168.             result.append(str(remainder // int(b)))
  169.             remainder %= int(b)

  170.         result = ''.join(result).lstrip('0') or '0'

  171.         # print(result)

  172.         int_part = (
  173.             result[:-precision -1]
  174.             if (
  175.                 (self.int_part is None) or (other.int_part is None)
  176.             )
  177.             else result[:-precision]
  178.         ) or '0'
  179.         # print(int_part)

  180.         frac_part = result[-precision:] or '0'

  181.         if preprocessing_flag:

  182.             self.frac_part = "".join(
  183.                 [
  184.                     self.int_part,
  185.                     self.frac_part
  186.                 ]
  187.             )
  188.             self.int_part = None

  189.             other.frac_part = "".join(
  190.                 [
  191.                     other.int_part,
  192.                     other.frac_part
  193.                 ]
  194.             )
  195.             other.int_part = None

  196.         return int_part, frac_part

  197.     def _abs_greater(self, other):

  198.         if len(self.int_part) != len(other.int_part):
  199.             return len(self.int_part) > len(other.int_part)

  200.         if self.int_part != other.int_part:
  201.             return self.int_part > other.int_part

  202.         return self.frac_part > other.frac_part

  203.     def pos(self):
  204.         pass

  205.     def neg(self):
  206.         self.negative = False if self.negative else True

  207. # Example usage:


  208. if __name__ == "__main__":
  209.     a = HighPrecisionFloat("0.1")
  210.     b = HighPrecisionFloat("0.2")

  211.     print("Addition:", str(a + b))
  212.     print("Subtraction:", str(a - b))
  213.     print("Multiplication:", str(a * b))
  214.     print("Division:", str(a / b))

  215.     print(a, b)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-26 19:30:32 | 显示全部楼层
这段代码定义了一个 `HighPrecisionFloat` 类,用于进行高精度浮点数运算。以下是修复代码中未完成部分的要点:

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

  1. def _add_abs(self, other):
  2.     a_int, a_frac, b_int, b_frac = self._align_parts(other)
  3.     carry = 0
  4.     frac_sum = []

  5.     # 处理小数部分的加法
  6.     for i in range(len(a_frac) - 1, -1, -1):
  7.         sum_val = int(a_frac[i]) + int(b_frac[i]) + carry
  8.         carry = sum_val // 10
  9.         frac_sum.append(str(sum_val % 10))

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

  12.     int_sum = []
  13.     a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), b_int.zfill(max(len(a_int), len(b_int)))

  14.     # 处理整数部分的加法
  15.     for i in range(len(a_int) - 1, -1, -1):
  16.         sum_val = int(a_int[i]) + int(b_int[i]) + carry
  17.         carry = sum_val // 10
  18.         int_sum.append(str(sum_val % 10))

  19.     if carry:
  20.         int_sum.append(str(carry))

  21.     int_sum.reverse()
  22.     int_sum = ''.join(int_sum).lstrip('0') or '0'

  23.     return int_sum, frac_sum
复制代码


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

  1. def _sub_abs(self, other):
  2.     a_int, a_frac, b_int, b_frac = self._align_parts(other)
  3.     borrow = 0
  4.     frac_diff = []

  5.     # 处理小数部分的减法
  6.     for i in range(len(a_frac) - 1, -1, -1):
  7.         diff = int(a_frac[i]) - int(b_frac[i]) - borrow
  8.         if diff < 0:
  9.             diff += 10
  10.             borrow = 1
  11.         else:
  12.             borrow = 0
  13.         frac_diff.append(str(diff))

  14.     frac_diff.reverse()
  15.     frac_diff = ''.join(frac_diff).rstrip('0') or '0'

  16.     int_diff = []
  17.     a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), b_int.zfill(max(len(a_int), len(b_int)))

  18.     # 处理整数部分的减法
  19.     for i in range(len(a_int) - 1, -1, -1):
  20.         diff = int(a_int[i]) - int(b_int[i]) - borrow
  21.         if diff < 0:
  22.             diff += 10
  23.             borrow = 1
  24.         else:
  25.             borrow = 0
  26.         int_diff.append(str(diff))

  27.     int_diff.reverse()
  28.     int_diff = ''.join(int_diff).lstrip('0') or '0'

  29.     return int_diff, frac_diff
复制代码


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

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

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

  4.     print("Addition:", str(a + b))
  5.     print("Subtraction:", str(a - b))
  6.     print("Multiplication:", str(a * b))
  7.     print("Division:", str(a / b))
复制代码


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

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

点评

你干嘛!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  发表于 2024-10-26 19:33

评分

参与人数 1荣誉 -5 贡献 -3 收起 理由
zhangchenyvn -5 -3 请不要无意义灌水!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-26 19:33:45 | 显示全部楼层
我就是因为很讨厌decimal库才写的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-26 19:33:59 | 显示全部楼层
zhangchenyvn 发表于 2024-10-26 19:33
我就是因为很讨厌decimal库才写的


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

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

  1. def _add_abs(self, other):
  2.     a_int, a_frac, b_int, b_frac = self._align_parts(other)
  3.     carry = 0
  4.     frac_sum = []

  5.     # 小数部分加法
  6.     for i in range(len(a_frac) - 1, -1, -1):
  7.         sum_val = int(a_frac[i]) + int(b_frac[i]) + carry
  8.         carry = sum_val // 10
  9.         frac_sum.append(str(sum_val % 10))

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

  12.     int_sum = []
  13.     a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), b_int.zfill(max(len(a_int), len(b_int)))

  14.     # 整数部分加法
  15.     for i in range(len(a_int) - 1, -1, -1):
  16.         sum_val = int(a_int[i]) + int(b_int[i]) + carry
  17.         carry = sum_val // 10
  18.         int_sum.append(str(sum_val % 10))

  19.     if carry:
  20.         int_sum.append(str(carry))

  21.     int_sum.reverse()
  22.     int_sum = ''.join(int_sum).lstrip('0') or '0'

  23.     return int_sum, frac_sum
复制代码


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

  1. def _sub_abs(self, other):
  2.     a_int, a_frac, b_int, b_frac = self._align_parts(other)
  3.     borrow = 0
  4.     frac_diff = []

  5.     # 小数部分减法
  6.     for i in range(len(a_frac) - 1, -1, -1):
  7.         diff = int(a_frac[i]) - int(b_frac[i]) - borrow
  8.         if diff < 0:
  9.             diff += 10
  10.             borrow = 1
  11.         else:
  12.             borrow = 0
  13.         frac_diff.append(str(diff))

  14.     frac_diff.reverse()
  15.     frac_diff = ''.join(frac_diff).rstrip('0') or '0'

  16.     int_diff = []
  17.     a_int, b_int = a_int.zfill(max(len(a_int), len(b_int))), b_int.zfill(max(len(a_int), len(b_int)))

  18.     # 整数部分减法
  19.     for i in range(len(a_int) - 1, -1, -1):
  20.         diff = int(a_int[i]) - int(b_int[i]) - borrow
  21.         if diff < 0:
  22.             diff += 10
  23.             borrow = 1
  24.         else:
  25.             borrow = 0
  26.         int_diff.append(str(diff))

  27.     int_diff.reverse()
  28.     int_diff = ''.join(int_diff).lstrip('0') or '0'

  29.     return int_diff, frac_diff
复制代码


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

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-27 09:10:19 | 显示全部楼层

回帖奖励 +2 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-27 13:11:12 | 显示全部楼层

回帖奖励 +2 鱼币

卧槽这是
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-27 19:09:29 | 显示全部楼层

手写加减
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-28 09:07:21 | 显示全部楼层

回帖奖励 +2 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-28 10:37:28 | 显示全部楼层

回帖奖励 +2 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-30 19:07:48 | 显示全部楼层

回帖奖励 +2 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-11-12 10:01:07 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-8 04:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表