我刚刚开始编程,我遇到了一个我似乎无法弄清楚的问题。我写了这个函数,isPrime
似乎总是通过相等测试。我可以确认factorial
函数是有效的,因为我已经单独测试了它。
威尔逊定理指出,如果(p - 1),则数p为素数! + 1是p的倍数。
#include <stdio.h>
#include <math.h>
void isPrime(double p);
double factorial(double n);
int main(void) {
double userInput;
while(1) {
scanf("%lf", &userInput);
isPrime(userInput);
}
return 0;
}
//
double factorial(double n) {
if(n <= 1)
return n;
else
return n * factorial(n - 1);
}
void isPrime(double p) {
if(modf(factorial(p - 1) + 1, &p) == 0)
printf("Prime!\n");
else
printf("Not prime!\n");
}
答案 0 :(得分:4)
不要使用双精度来保持整数。舍入错误将使完全平等的测试变得虚假。请参阅“What Every Computer Scientist Should Know about Floating Point”。
答案 1 :(得分:3)
double
无法准确存储因子。从那时起,您的结果将完全是假的。如果你想用威尔逊定理进行素性测试,可以使用模运算,
uint64_t modFactorial(uint64_t n, uint64_t m) {
uint64_t f = 1;
for(; n > 1; --n) {
f = (n*f) % m;
}
return f;
}
int isPrime(uint64_t p) {
if (p < 2) return 0;
return modFactorial(p-1,p) + 1 == p;
}
可以正确处理小于2 ^ 32的输入。然而,它相当缓慢,威尔逊定理不是在实践中测试素性的好方法,它的价值在于数论中的应用。
如果您需要处理大型整数,请使用GMP(附带 - 概率 - 素数测试)。
答案 2 :(得分:1)
modf
不像您期望的那样执行模数。引用:
The modf() break value into integral and fractional parts, each of which
has the same sign as the argument. They return the fractional part, and
store the integral part (as a floating-point number) in the object
pointed to by iptr
您希望fmod
和朋友代替modf
。
答案 3 :(得分:0)
您的代码中有一个小错误。
将测试更改为以下内容:
if (modf((factorial(p - 1) + 1)/p, &p) == 0)
另外,正如其他人指出的那样,使用双打可能不是最佳选择。
答案 4 :(得分:-1)
我的猜测是你的阶乘函数返回0因为(n <= 1)允许返回n = 0。