【问题标题】:Pattern matching of remainders in long division长除法余数的模式匹配
【发布时间】:2016-01-24 15:15:05
【问题描述】:

我有一个有效的算法来确定分数是否无限重复以及哪些数字在重复:

std::vector<integer_type> rd, dg;
integer_type d ( m_numer ), r;

do {

    integer_type q, aux;

    rd.push_back ( r = ( aux = _remquo<T, GCD, CHKOP> () ( d, m_denom, q ) ) < zero_ ?
                       integer_type ( -aux ) : aux );
    dg.push_back ( q < zero_ ? integer_type ( -q ) : q );

    d = op_multiplies() ( base, r );

} while ( ! ( r == zero_ || std::find ( rd.rbegin() + 1, rd.rend(), r ) != rd.rend() ) );

注意事项:

  • rd 包含余数
  • dg 包含十进制结果数字
  • _remquo整数将第一个和第二个操作数相除并将余数存储在第三个参数中,忽略模板参数
  • base 可以认为是10 的十进制值
  • m_numer 是分数的分子
  • m_denom 是分数的分母

问题:

我想至少去掉std::find ( rd.rbegin() + 1, rd.rend(), r ) != rd.rend() ),即我想检测之前是否已经出现了余数(也最好去掉rd向量)最后一位数字之间的距离从右到左到rd 中的第一个重复数字。

问题是,我想在合理的时间内(无需花费反向搜索余数向量的时间)分析具有 HUGE 重复数字序列的数字,如 1083448249/12172166。

有人有什么想法吗?

【问题讨论】:

  • 直接计算重复数字,而不是实际做长除法来检测重复数字不是更容易吗?
  • @JSF 欢迎您向我展示任何其他算法来做到这一点。我需要最终结果以及重复数字和(如果有的话)点之后的非重复数字。 13/30 => 0.4(3)
  • @HeikoSchäfer 问题可以简化为1/N 的情况。对于这种情况,请阅读:mathforum.org/library/drmath/view/51549.html(可以推广到任何基础)。
  • @freakish 谢谢你的链接。我会通过它:)
  • 根据Wikipedia,“if”可以通过素因数分解来解决。您还可以通过代数方式找到重复的长度,因此您知道何时找到它。当然,能否在合理时间内解决是另一个问题。

标签: c++ algorithm


【解决方案1】:

直接计算十进制扩展的位数,无需大数。使用弗洛伊德的周期检测方法来计算周期。在 Python 中(循环检测代码由 Wikipedia 提供):

#!/usr/bin/env python3
def floyd(f, x0):
    tortoise = f(x0)
    hare = f(f(x0))
    while tortoise != hare:
        tortoise = f(tortoise)
        hare = f(f(hare))
    mu = 0
    tortoise = x0
    while tortoise != hare:
        tortoise = f(tortoise)
        hare = f(hare)
        mu += 1
    lam = 1
    hare = f(tortoise)
    while tortoise != hare:
        hare = f(hare)
        lam += 1
    return (lam, mu)


def repeating_decimal(n, d):
    q, r = divmod(n, d)
    decimal = [str(q), '.']
    period, first_repeat = floyd(lambda r: 10 * r % d, r)
    for i in range(first_repeat + period):
        q, r = divmod(10 * r, d)
        decimal.append(str(q))
    return '{}({})'.format(''.join(decimal[:2 + first_repeat]), ''.join(decimal[2 + first_repeat:]))


print(repeating_decimal(1, 75))
print(repeating_decimal(1083448249, 12172166))

【讨论】:

  • 天啊!好的,它是python和另一种算法,但我想我会把它转换成C++并试一试:)
  • @HeikoSchäfer 对我来说最舒服的语言,可以在墙上扔黑客。当您将 lambda 内联到循环检测器时,就有机会进行简化。
  • 你成就了我的一天 :) 我已将其转换为 C++ 并将其(甚至未优化)集成到我的代码中,而且 ALL 测试用例运行没有错误!谢谢:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 2021-03-12
  • 2019-05-01
  • 2017-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多