C# Miller-Rabin素性测试在大数情况下失败
在研究了与Miller-Rabin素数测试相关的其他答案后,我用C#实现了一个版本,但它偶尔会在30亿左右的某个地方失败,当它达到40亿时,它就不再识别任何素数了。我怀疑我正在遭受溢流,但不知道在哪里。我的目标是使其适用于0=1范围内的任何值; } 随机r=新随机(); for(int i=0;iC# Miller-Rabin素性测试在大数情况下失败,c#,primes,prime-factoring,C#,Primes,Prime Factoring,在研究了与Miller-Rabin素数测试相关的其他答案后,我用C#实现了一个版本,但它偶尔会在30亿左右的某个地方失败,当它达到40亿时,它就不再识别任何素数了。我怀疑我正在遭受溢流,但不知道在哪里。我的目标是使其适用于0=1范围内的任何值; } 随机r=新随机(); for(int i=0;i(a^2)^9*a->((a^2)^2)^4*(a^2))*a->(((a^2)^2)^2*(a^2))*a 如果(b==0L)返回1L; 如果(a==0L)返回0L; 如果(b==1L)返回%n; v
const long _2_32=1L终于找到了问题:RussianPeasant。我没有测试每个边缘情况。我的溢出限制应该是2^31,而不是2^32,以说明符号位。下面是更正的方法:
public static long RussianPeasant(long a, long b, long c)
{
const long overflow_limit = 1L << 31;
a = Math.Abs (a);
b = Math.Abs (b);
if (a < overflow_limit && b < overflow_limit)
return (a * b % c); // No possibility of overflow.
if (c < overflow_limit)
return (a % c) * (b % c) % c;
long ret = 0;
while(b != 0) {
if((b&1L) != 0L) {
ret += a;
ret %= c;
}
a *= 2;
a %= c;
b /= 2;
}
return ret;
}
publicstaticlong-RussianPeasant(长a、长b、长c)
{
const long overflow_limit=1L“我怀疑我正在遭受溢出”——是的,这似乎很可能。“无法找出在哪里”--为什么不呢?你尝试了什么?你有没有在失败的情况下观察你的变量是否溢出?你有没有用检查过的算术编译你的程序,这样当溢出发生时它会抛出异常?堆栈溢出是一个很好的调试帮助的地方;不是一个让别人来调试的好地方为您。尝试了以下方法:为ModulePower编写单元测试(在我的代码示例中未显示)他们都通过了。为iPrime编写了许多单元测试——低数字通过,高数字失败。低数字测试一致成功的事实是我认为溢出是一个问题的线索。我不想让其他人帮我调试。经过两天大约十个小时的调试,阅读了许多SO帖子还有几篇C.S.和数学论文,我向你保证,你在不寻求帮助的情况下尽一切努力解决了我的问题。这就是我发现许多C#运算的定义与数学论文中引用的函数略有不同,例如mod vs%,GCD等。这项研究让我想到了俄罗斯农民和ModPower的想法,还有基础的“最佳”价值。正是这些边缘案例一直在折磨着我,因为我的直觉让我失望。
public static long RussianPeasant(long a, long b, long c)
{
const long overflow_limit = 1L << 31;
a = Math.Abs (a);
b = Math.Abs (b);
if (a < overflow_limit && b < overflow_limit)
return (a * b % c); // No possibility of overflow.
if (c < overflow_limit)
return (a % c) * (b % c) % c;
long ret = 0;
while(b != 0) {
if((b&1L) != 0L) {
ret += a;
ret %= c;
}
a *= 2;
a %= c;
b /= 2;
}
return ret;
}