【问题标题】:Longest recurring cycle in its decimal fraction - a bug or a misunderstanding?十进制中最长的循环周期 - 错误还是误解?
【发布时间】:2011-11-10 08:44:56
【问题描述】:

这是相当“数学问题”,但我在这里发帖是因为这是一个 Project Euler 问题,而且我的工作代码可能存在错误。

问题Determing longest repeating cycle in a decimal expansion 使用对数解决问题,但我有兴趣用简单的蛮力解决问题。更准确地说,我有兴趣了解为什么我的算法和代码没有返回正确的解决方案。

算法很简单:

  • 复制“长除法”,
  • 在每一步记录除数和余数
  • 当一个除数/余数元组重复时,推断十进制表示会重复。

这里是私有字段,根据要求

private int numerator; 
private int recurrence; 
private int result; 
private int resultRecurrence; 
private List<dynamic> digits;

这里是代码:

private void Go()
{
    foreach (var i in primes)
    {
        digits = new List<dynamic>();
        numerator = 1;
        recurrence = 0;

        while (numerator != 0)
        {
            numerator *= 10;

            // quotient
            var q = numerator / i;

            // remainder
            var r = numerator % i;
            digits.Add(new { Divisor = q, Remainder = r });

            // if we've found a repetition then break out
            var m = digits.Where(p => p.Divisor == q && p.Remainder == r).ToList();
            if (m.Count > 1)
            {
                recurrence = digits.LastIndexOf(m[0]) - digits.IndexOf(m[0]);
                break;
            }
            numerator = r;
        }

        if (recurrence > resultRecurrence)
        {
            resultRecurrence = recurrence;
            result = i;
        }
}}

当测试整数 i 的值。但是,我得到的十进制表示不正确 - 我计算 i-1 而正确的结果要少得多(类似于 i-250)。

所以大概我有一个编程错误 - 我找不到 - 或者一个逻辑错误。

我很困惑,因为它对我来说就像multiplicative group over p,其中会有 p-1 个元素。我确定我错过了什么,有人可以提供建议吗?

编辑

我不会包含我的素数代码 - 这不相关,正如我在上面解释的那样,我正确识别了 i 的值(从内存中它是 983),但是我在获取正确的值时遇到了问题resultRecurrence.

【问题讨论】:

  • 您能告诉我们您使用哪种语言编写代码吗?我以为是javascript,然后意识到不可能。
  • @Phil - 添加了 c# 标签 - 这不是 c# 特定的问题,但我想标签属于。
  • 你能发布整个代码,其中变量primesdigitsnumeratorrecurrenceresultRecurrenceresult 被声明了吗?如果这些是方法的参数,请向我们展示方法签名以及如何调用它。
  • 你有什么理由使用弱类型的List
  • @Kirk dynamic 是使用反射的便捷快捷方式。这在与 IronPython 等动态语言/库交互时是必需的。

标签: c# math logic


【解决方案1】:

我很困惑,因为它对我来说感觉就像一个 p 上的乘法群,其中会有 p-1 个元素。我确定我错过了什么,有人可以提供建议吗?

关闭。

对于除 2 和 5(除以 10)之外的所有素数,余数序列由从 1 开始并变换为

remainder = (10 * remainder) % prime

因此第 k 个余数是 10k(模素数),余数集形成非零群的子群余数模素数[1]。循环周期的长度就是那个子群的阶数,也就是所谓的10模素数阶。

非零余数模素数的阶数为prime-1,有一个费马定理:

G 是一个有限阶序gHG 的一个子群。那么h的顺序H除以g

所以循环的长度总是prime-1的除数,有时是prime-1,例如7 或 19。

[1] 对于合数 n 互质为 10,这将是余数模 nn 互质的组。

【讨论】:

    【解决方案2】:

    首先,你不需要除数,你只需要余数。

    其次,我会将函数拆分为多个独立的部分,而不是将所有内容都放在一个大方法中:循环长度的长除法/查找与其余部分无关(= 查找最长的循环)。

    Where 上的 break 加上 Count 是不直观的。为什么不直接使用带有条件(! digits.Contains(r))while 循环呢? (这需要在循环开始之前将0 作为余数放入digits 列表中。)

    这给我们留下了更简洁的代码,应该可以直接调试。

    【讨论】:

    • 我最初是从查看数字而不是余数开始的;然后我决定我需要查看余数,但保留数字。你是对的 - 不需要在算法中保留数字计算或存储。
    【解决方案3】:
    recurrence = digits.LastIndexOf(m[0]) - digits.IndexOf(m[0]);
    

    resultRecurrence 的值肯定是 总是 将是 i-1 吗?因为对于1/n 形式的一小部分,当进行中的除法(ith 数字)给出与 第一个试除法相同的商余数时,小数开始重复(1,因此是i-1)。

    (作为旁注,我可以向您介绍Math.DivRem)。

    【讨论】:

    • 我做了同样的假设,但正如你在我的问题中看到的那样,这不是正确答案(根据我倾向于相信的欧拉计划)跨度>
    • 假设是错误的:有些数字的循环不是从小数点后开始的。如果您将i - 1 作为答案,这将假定循环从第一个十进制数字开始。
    猜你喜欢
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2022-01-16
    • 2014-10-12
    • 1970-01-01
    • 2021-11-03
    相关资源
    最近更新 更多