小数部分中最长的循环周期 - 错误还是误解?

时间:2011-09-05 04:46:03

标签: c# math logic

这是'数学',但我在这里发帖是因为它是项目欧拉问题,&我有可能有错误的工作代码。

问题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;
        }
}}

测试整数时&lt; 10和&lt; 20我得到了正确的结果;我也正确地确定了i的价值。然而,我得到的十进制表示不正确 - 我计算i-1而正确的结果远远少于i-250

所以我可能有一个编程错误 - 我找不到 - 或者是一个逻辑错误。

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

修改

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

3 个答案:

答案 0 :(得分:2)

  

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

关闭。

对于除2和5(除以10)之外的所有素数,剩余序列是通过从1开始并通过

转换而形成的。
remainder = (10 * remainder) % prime

因此 k -th余数为10 k (mod prime),剩余集合形成非零组的子组余数模数[1]。循环周期的长度是该子组的顺序,也称为10模数的阶数。

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

  

G成为订单g的有限组,HG的子组。然后,h的订单H除以g

因此,周期的长度始终是prime-1的除数,有时它是prime-1,例如为7或19。

[1]对于复合数n互译为10,这将是模n的余数组n

答案 1 :(得分:1)

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

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

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

这给我们留下了一个更清晰的代码,应该可以直接调试。

答案 2 :(得分:1)

recurrence = digits.LastIndexOf(m[0]) - digits.IndexOf(m[0]);

resultRecurrence的值总是将是i-1?因为对于1/n形式的一小部分,当正在进行的除法(i数字)给出与第一个相同的商 - 余数时,十进制开始重复。 em>试验师(1,因此i-1)。

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