📜  在分数中查找重复序列(1)

📅  最后修改于: 2023-12-03 15:07:58.097000             🧑  作者: Mango

在分数中查找重复序列

简介

在数学中,经过有理数运算的数字可能会产生无限循环的序列。比如,1/3 = 0.33333…,其中 3 持续出现,构成了循环序列。对于一个分数,如果它的小数表示有循环序列,那么我们称它是一个循环小数。

在数学中,我们已经知道如何将一个分数转化成循环小数。而对于程序员来说,如何快速地找出循环序列成为了一个常见的问题。本篇文档将会介绍两种常见的解决方法。

方法一

第一种方法是通过 long division 转化法来找到循环序列。具体实现如下:

  • 将被除数乘 10,得到第一个商和第一个余数。
  • 把余数乘 10,并且和下一个数字做除法。得到下一个商和下一个余数。
  • 在每次求出商和余数之后,我们就需要进行重复序列的判断了。如果余数已经出现过了,那么我们就需要停止计算,返回已经求出的商。

代码示例(python):

def find_recurring_cycle(p, q):
  remainder_dict = {}
  remainder = p % q
  recurring_cycle = []
  while remainder != 0 and remainder not in remainder_dict:
    remainder_dict[remainder] = len(recurring_cycle)
    quotient, remainder = divmod(10 * remainder, q)
    recurring_cycle.append(str(quotient))
  if remainder == 0:
    return None
  else:
    return recurring_cycle[remainder_dict[remainder]:]
方法二

第二个解决方法需要用到 Floyd Cycle Detection Algorithm。具体来说,我们可以使用快慢指针找到循环的起点。

  • 我们可以使用两个指针,一个 fast_pointer 以两倍速度移动,指向 the remainder of p * 10^(k+1) modulo q,另一个指针 slow_pointer 以一倍速度移动,指向 the remainder of p * 10^k modulo q,其中 k 是已经被计算出来的商的数量。
  • 如果存在循环序列,fast_pointer 和 slow_pointer 一定会相遇。此时,我们可以把 slow_pointer 重置为 the remainder of p modulo q,并且把 fast_pointer 变为以一个单位的速度移动。
  • 我们接下来通过移动 fast_pointer 和 slow_pointer 来寻找循环的起点。当两个指针再次相遇时,它一定是循环的起点。

代码示例(python):

def find_recurring_cycle(p, q):
  fast_pointer = p % q
  slow_pointer = p % q
  length = 0
  while True:
    length += 1
    fast_pointer = (fast_pointer * 10) % q
    slow_pointer = (slow_pointer * 10) % q
    fast_pointer = (fast_pointer * 10) % q
    if fast_pointer == slow_pointer:
      break
  slow_pointer = p % q
  for i in range(length):
    fast_pointer = (fast_pointer * 10) % q
  while fast_pointer != slow_pointer:
    fast_pointer = (fast_pointer * 10) % q
    slow_pointer = (slow_pointer * 10) % q
  if slow_pointer == 0:
    return None
  else:
    return str(slow_pointer)
结论

在本篇文章中,我们介绍了两种常见的方法来找到循环小数中的重复序列。第一种方法是通过 long division 转化法来找到重复序列,第二种方法是使用 Floyd Cycle Detection Algorithm 通过快慢指针找到循环的起点。在实际中,我们可以根据具体情况选择适合自己的解决方法。