如何无近似地精确转换循环二进制数与十进制数
精确循环进制转换实现方案
要实现二进制循环数与十进制循环数的精确转换,核心思路是借助分数作为中间载体——所有循环小数本质都是有理数,可精确表示为分数,从而彻底避免浮点误差。以下是具体实现:
依赖与基础函数
首先导入fractions模块处理精确分数,实现基础的字符串转整数函数:
from fractions import Fraction def read_int(s: str, base: int) -> int: """将指定基数的字符串转换为整数,空字符串返回0""" return int(s, base) if s else 0
二进制循环数 → 十进制循环数
转换逻辑
- 将二进制三元组
(整数部分, 有限小数部分, 循环节)转换为分数:
设二进制数为I.F(R)_2,则对应的分数公式为:
$$N = \frac{(I \times 2^k + F) \times (2^m - 1) + R}{2^k \times (2^m - 1)}$$
其中k是有限小数部分长度,m是循环节长度。 - 对分数执行十进制长除法,通过记录余数出现的位置识别循环节,拆分出十进制三元组。
代码实现
def binary_cycle_to_decimal_cycle(binary_triple: tuple[str, str, str]) -> tuple[str, str, str]: """ 将二进制循环数三元组转换为精确十进制循环数三元组 :param binary_triple: (整数部分字符串, 有限小数部分字符串, 循环节字符串) :return: 对应的十进制循环数三元组 """ integer_str, finite_str, period_str = binary_triple base = 2 k = len(finite_str) m = len(period_str) I = read_int(integer_str, base) F = read_int(finite_str, base) R = read_int(period_str, base) # 处理整数情况 if k == 0 and m == 0: return (str(I), '', '') # 计算分数的分子和分母 if m == 0: numerator = I * (base ** k) + F denominator = base ** k else: numerator = (I * (base ** k) + F) * ((base ** m) - 1) + R denominator = (base ** k) * ((base ** m) - 1) # 用Fraction存储精确分数并自动约分 fr = Fraction(numerator, denominator) # 将分数转换为十进制循环三元组 return fraction_to_decimal_triple(fr) def fraction_to_decimal_triple(fr: Fraction) -> tuple[str, str, str]: """将分数转换为十进制循环数三元组""" integer_part = fr.numerator // fr.denominator remainder = fr.numerator % fr.denominator # 有限小数或整数 if remainder == 0: return (str(integer_part), '', '') decimal_digits = [] remainder_map = {} # 记录余数对应的小数位位置,用于识别循环节 pos = 0 while remainder != 0: if remainder in remainder_map: # 找到循环起始位置,拆分有限部分和循环节 start_idx = remainder_map[remainder] finite_part = decimal_digits[:start_idx] repeating_part = decimal_digits[start_idx:] return (str(integer_part), ''.join(finite_part), ''.join(repeating_part)) remainder_map[remainder] = pos remainder *= 10 digit = remainder // fr.denominator decimal_digits.append(str(digit)) remainder = remainder % fr.denominator pos += 1 # 无循环节的有限小数 return (str(integer_part), ''.join(decimal_digits), '')
十进制循环数 → 二进制循环数
转换逻辑
- 将十进制三元组转换为分数,公式类似二进制转十进制:
设十进制数为I.F(R)_10,对应的分数公式为:
$$N = \frac{(I \times 10^k + F) \times (10^m - 1) + R}{10^k \times (10^m - 1)}$$ - 对分数执行二进制长除法,识别循环节,拆分出二进制三元组。
代码实现
def decimal_cycle_to_binary_cycle(decimal_triple: tuple[str, str, str]) -> tuple[str, str, str]: """ 将十进制循环数三元组转换为精确二进制循环数三元组 :param decimal_triple: (整数部分字符串, 有限小数部分字符串, 循环节字符串) :return: 对应的二进制循环数三元组 """ integer_str, finite_str, period_str = decimal_triple base = 10 k = len(finite_str) m = len(period_str) I = read_int(integer_str, base) F = read_int(finite_str, base) R = read_int(period_str, base) # 处理整数情况 if k == 0 and m == 0: return (bin(I)[2:], '', '') # 计算分数的分子和分母 if m == 0: numerator = I * (base ** k) + F denominator = base ** k else: numerator = (I * (base ** k) + F) * ((base ** m) - 1) + R denominator = (base ** k) * ((base ** m) - 1) fr = Fraction(numerator, denominator) # 将分数转换为二进制循环三元组 return fraction_to_binary_triple(fr) def fraction_to_binary_triple(fr: Fraction) -> tuple[str, str, str]: """将分数转换为二进制循环数三元组""" integer_part = fr.numerator // fr.denominator remainder = fr.numerator % fr.denominator # 有限小数或整数 if remainder == 0: return (bin(integer_part)[2:], '', '') binary_digits = [] remainder_map = {} pos = 0 while remainder != 0: if remainder in remainder_map: # 找到循环起始位置 start_idx = remainder_map[remainder] finite_part = binary_digits[:start_idx] repeating_part = binary_digits[start_idx:] return (bin(integer_part)[2:], ''.join(finite_part), ''.join(repeating_part)) remainder_map[remainder] = pos remainder *= 2 digit = remainder // fr.denominator binary_digits.append(str(digit)) remainder = remainder % fr.denominator pos += 1 # 无循环节的有限小数 return (bin(integer_part)[2:], ''.join(binary_digits), '')
测试示例
# 二进制转十进制测试 binary_input = ('10', '1', '010') decimal_output = binary_cycle_to_decimal_cycle(binary_input) print(f"二进制{binary_input} → 十进制{decimal_output}") # 输出:二进制('10', '1', '010') → 十进制('2', '6', '428571') # 十进制转二进制测试 decimal_input = ('2', '6', '428571') binary_output = decimal_cycle_to_binary_cycle(decimal_input) print(f"十进制{decimal_input} → 二进制{binary_output}") # 输出:十进制('2', '6', '428571') → 二进制('10', '1', '010')
内容的提问来源于stack exchange,提问作者Tar-Roccorendil
相关产品推荐
相关产品推荐

