C 涉及Wilson'的素性检验;s定理没有按计划工作

C 涉及Wilson'的素性检验;s定理没有按计划工作,c,C,我刚刚开始编程,遇到了一个似乎无法解决的问题。我编写了这个函数,isPrime,它似乎总是通过平等性测试。我可以确认,factorial函数是有效的,因为我已经单独测试了它 威尔逊定理指出,如果(p-1)!+1是p的倍数 #include <stdio.h> #include <math.h> void isPrime(double p); double factorial(double n); int main(void) { double userInpu

我刚刚开始编程,遇到了一个似乎无法解决的问题。我编写了这个函数,
isPrime
,它似乎总是通过平等性测试。我可以确认,
factorial
函数是有效的,因为我已经单独测试了它

威尔逊定理指出,如果(p-1)!+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");
}
#包括
#包括
无效质(双p);
双阶乘(双n);
内部主(空){
双用户输入;
而(1){
scanf(“%lf”、&userInput);
iPrime(用户输入);
}
返回0;
}
//
双阶乘(双n){

如果(n
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

不要使用双精度来保存整数。舍入错误将使相等测试完全是假的。请参阅“”。

我猜您的阶乘函数返回0,因为(n您的代码中有一个小错误

将测试更改为以下内容:

if (modf((factorial(p - 1) + 1)/p, &p) == 0)

另外,正如其他人指出的,使用双精度可能不是最好的方法。

double
如果n大于23左右,则无法准确存储阶乘。从那时起,您的结果将完全是假的。如果您想使用威尔逊定理进行素性测试,请使用模运算

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;
}
uint64-modFactorial(uint64-n,uint64-m){
uint64_t f=1;
对于(;n>1;--n){
f=(n*f)%m;
}
返回f;
}
int iPrime(uint64\u t p){
if(p<2)返回0;
返回因子(p-1,p)+1==p;
}
它可以正确地处理小于2^32的输入。然而,它相当慢,威尔逊定理在实践中不是检验素性的好方法,它的价值在于在数论中的应用


如果您需要处理大整数,请使用GMP(随-概率-素性测试一起提供)。

您是否尝试打印收到的内容?(
printf(“%lf Prime!\n”,p)
)这段代码不适用于大数的素性测试。我需要这段代码来处理非常大的数,大于一个int所能容纳的数。顺便感谢链接!@isosine,对大的非单整数使用
unsigned long long
。使用
double
是完全没有用的。@isosine:如果你使用
double
你的非常大的数字将是近似值,因此您的测试将完全没有意义。您可能需要使用一些大整数库(例如GMP).噢,哇,我还没意识到还有另一个这样的函数。真是个误会。无论如何,非常感谢!这似乎解决了问题。@isosine如果我的回答解决了你的问题,请接受:)