代码:
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;
}
该程序基于Fermat关于素数的定理。 N是要作为素数进行测试的数字。该程序未显示'11'的正确结果。也许是因为我发现了一些错误。
答案 0 :(得分:2)
如果这是伪代码或
,您将遇到溢出
如果使用C代码,则使用^
作为幂运算符无效。
使用大整数很快成为C中的问题。可以使用各种BigInt
库。
使用大整数计算时,使用浮点具有挑战性。建议避免double
,pow()
等
由于问题都是&gt; = 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
的替代方案。
答案 1 :(得分:1)
如果我将你的代码读作伪代码,你就会溢出。
10^10
大于2^31 -1
,这是大多数int
的最大值。你可以通过使用long来解决N=11
这个问题,但这不会让你走得太远,你也会在某些时候开始溢出。
这个定理,至少表达方式,与有限长度的数字一起使用是非常不切实际的。
现在,如果您的代码是真实的C
,请注意^
表示XOR
,而不是取幂。指数为pow()
。感谢评论者指出这一点。
答案 2 :(得分:0)
这里可以应用模块化的数学规则和原则来表明为了计算
(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
可以很容易地计算而不用担心任何溢出。
再次使用Modular Multiplication身份,我们知道
(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技术也存在。这只是一个例子,展示了如何使用模块化数学技术来实现费马的小素性测试。
干杯!
答案 3 :(得分:0)
抱歉,请稍稍更改您的代码。使用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
}