【问题标题】:Primality test using Fermat little theorem使用费马小定理进行素性检验
【发布时间】:2013-10-16 10:07:20
【问题描述】:

代码:

void prime()    
{    
    int i,N;    
    scanf("%d",&N);    
    for(i=2;i<N;i++)            
    {    
        if (((i^(N-1))%N )==1);     
        else{    
            printf("not prime");   
            return;
        }     
    }    
    printf("prime");    
    return;    
}    

该程序基于关于素数的费马定理。 N 是要作为素数进行测试的数。该程序未显示“11”的正确结果。可能是因为一些我没有发现的错误。

【问题讨论】:

    标签: c primality-test


    【解决方案1】:

    如果我把你的代码读成伪代码,你就溢出了。

    10^10 大于2^31 -1,这是大多数int 的最大值。您可以使用 long 为 N=11 解决这个问题,但这不会让您走得太远,您也会在某个时候开始溢出。

    这个定理,至少是这样表达的,对于有限长度的数字是非常不切实际的。

    现在,如果您的代码是真实的C,请注意^ 表示XOR,而不是求幂。求幂是pow()。感谢评论者指出这一点。

    【讨论】:

    • 你们是对的,我只是检查了伪代码。让我修改我的答案
    【解决方案2】:

    如果这是伪代码
    ,您将遇到溢出 如果是 C 代码,使用^ 作为幂运算符是无效的。

    处理大整数很快成为 C 中的一个问题。有各种可用的BigInt 库。

    在大整数计算中使用浮点具有挑战性。建议避开doublepow()等。

    由于问题都是 >= 0,建议使用无符号整数。还要使用可用的最大整数类型 - 通常是 unsigned long long。由于溢出是一种真实的可能性,请检测它。

    unsigned long long upower(unsigned i, unsigned N) {
      unsigned long long power = 1;
      if (i <= 1) return i;
      while (N-- > 0) {
        unsigned long long power_before = power;
        power *= i;
        if (power < power_before) {
          printf("Overflow\n");
          return 0;
        }
      }
      return power;
    }
    
    void prime() {
      unsigned i, N;
      scanf("%u", &N);
      for (i = 2; i < N; i++) {
        if ((upower(i, N - 1) % N) != 1) {
          printf("not prime");
          return;
        }
      }
      printf("prime");
      return;
    }
    

    Chinese remainder theorem 可能提供(upower(i, N - 1) % N) != 1 的替代方案,而不是大整数。

    【讨论】:

    • 费马小定理是否给出任何整数的正确答案?如果不是,直到多少位数才能给出准确的解?
    • //@deathrace 依赖于ULLONG_MAX。对于 64 位 unsigned long long -> N &lt;= 16
    【解决方案3】:

    在这里可以应用模块化数学规则和原理来表明为了计算

    (i ^ (N-1)) % N,

    你甚至不需要一开始就计算 i^(N-1)。 您可以轻松地将 (N-1) 分解为 2 的幂。 让我们举个例子说得更清楚。

    假设我们的素数测试的主题,N = 58。

    所以,

    N - 1 = 57

    57 可以很容易地改写为:

    57 = 1 + 8 + 16 + 32

    或者,

    57 = 2^0 + 2^3 + 2^4 + 2^5

    所以,用这个值代替 N-1,我们需要计算

    (i ^ (2^0 + 2^3 + 2^4 + 2^5))% 58

    或者,

    ((i^1) × (i^8) × (i^16) × (i^32))% 58

    其中,使用Modular Multiplication 身份,可以重写为:

    ((i^1)% 58 × (i^8)% 58 × (i^16)% 58 × (i^32)% 58) mod 58 ---(1)

    请注意,

    (i^1)% 58 = i%58

    可以轻松计算而无需担心任何溢出。

    再次利用模乘恒等式,我们知道

    (i^2)% 58 = ((i^1)% 58 × (i^1)% 58)% 58

    代入(i^1)%58的值,求(i^2)%58。

    您可以继续以这种方式计算 (i^4)% 58 到 (i^32)% 58。一旦完成,您最终可以将 (1) 中的值替换为最终找到所需的值,非常有效地避免任何溢出。


    请注意,还存在其他 modular exponientation 技术。这只是展示如何使用模块化数学技术来实现 Fermat 的小素性检验的一个示例。

    干杯!

    【讨论】:

      【解决方案4】:

      很抱歉稍微更改您的代码。使用 BigInteger 类,您可以非常快速地计算更大的数字。但是,您可以使用此方法不按顺序获取素数,而是测试是否有素数。

      using System;
      using System.Numerics;
                          
      public class Program
      {
          public static void Main()
          {
              Console.WriteLine(2);
              for(var i = 3; i < 100000; i+=2) 
              {
                  if(BigInteger.ModPow(2, i , i) == 2)
                      Console.WriteLine(i);
              }
          }
      }
      

      https://dotnetfiddle.net/nwDP7h

      此代码在以下数字中会产生错误结果。

      https://oeis.org/a001567 https://oeis.org/a006935

      要修复这些错误,您需要编辑代码如下,并在这些数字中进行二进制搜索,以测试该数字是否为伪素数。

      public static bool IsPrime(ulong number)
      {
          return number == 2
              ? true
              : (BigInterger.ModPow(2, number, number) == 2
                  ? (number & 1 != 0 && BinarySearchInA001567(number) == false)
                  : false)
      }
      
      public static bool BinarySearchInA001567(ulong number)
      {
          // Is number in list?
          // todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
          // Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
      }
      

      【讨论】:

        猜你喜欢
        • 2013-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-30
        • 1970-01-01
        • 2015-06-18
        相关资源
        最近更新 更多