在用户输入的数字-C中查找最大素数

在用户输入的数字-C中查找最大素数,c,C,我的代码有问题。本课题是编写一个C程序,在用户输入的数字中找出最大素数 例: 输入号码:46656665326 产出:66566653 这是我的代码: #include <stdio.h> #include <stdlib.h> int is_prime(unsigned long long a) { if(a<=1) return 0; if(a==2) return 1; for(unsigned lon

我的代码有问题。本课题是编写一个C程序,在用户输入的数字中找出最大素数

例: 输入号码:46656665326

产出:66566653

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

int is_prime(unsigned long long a)
{
    if(a<=1)
        return 0;
    if(a==2)
        return 1;
    for(unsigned long long p=2; p<a; p++)
        if(a%p==0)
            return 0;
    return 1;
}

unsigned long long find_largest_prime_number(unsigned long long number)
{
    unsigned long long prime=0;
    int count=0;
    unsigned long long count2=1;
    unsigned long long pom=0;
    unsigned long long pom3=0;
    pom3=number;
    while(pom3!=0)
    {
        count++;
        pom3/=10;
    }
    count++;
    int pom_1=0;
    while(pom_1<count)
    {
        count2*=10;
        pom_1++;
    }
    pom=number;
    while(count2>=10)
    {
        unsigned long long pom2=pom;
        while(pom2!=0)
        {
            if(is_prime(pom2))
                if(pom2>prime)
                    prime=pom2;
            pom2/=10;
        }
        count2/=10;
        pom=pom%count2;
    }
    return prime;
}

int main()
{
    unsigned long long x=0;
    printf("Enter number: ");
    int n1=scanf("%llu", &x);
    if(n1!=1)
    {
        printf("incorrect input");
        return 1;
    }
    printf("%llu", find_largest_prime_number(x));
    return 0;
}
问题是,它可以使用最大13位数字,但当输入数字超过13位时,它会冻结。 当我进入时它会冻结:21591150493497


请帮助,代码出了什么问题?

阻塞的原因归结为:

int is_prime(unsigned long long a)
{
    ...
    for(unsigned long long p=2; p<a; p++)
        if(a%p==0)
            return 0;
    return 1;
}

以平方根为中心最终解决了这个问题。 is_prime应该是这样的:

int is_prime(unsigned long long a)
{
    int i=0;
    int count=0;
    int test=0;
    int limit=sqrt(a)+1;
    if(a<=1)
        return 0;
    if(a==2)
        return 1;
    if(a%2==0)
        test=1;
    else
        for(i=3; i<limit && !test; i+=2, count++)
            if(a%i==0)
                test=1;
    if(!test)
        return 1;
    else
        return 0;
}

你的代码完全正确。它的效率非常低,因此要花很长很长的时间才能确定一个大数是否为素数

以下是is_prime的更好版本:

它只测试被测数的平方根以下的除数。 它只测试奇数除数,如果这个数不能被2整除,那么测试它是否可以被4、6、8等整除是毫无意义的。
当然,进一步的优化是可能的。例如,如果数字不能被3整除,那么测试3的倍数也是毫无意义的。此外,如果你想找到一个素数范围,可能还有其他方法需要考虑。

正如其他贡献者所提到的,在注释中,你的代码崩溃仅仅是因为它效率低下

许多其他贡献者使用了一种更有效的方法来检查一个数是否为素数,方法是将该数与其除数进行比较

然而,这并不是最有效的方法,特别是如果你想知道多个数是否是素数

为了更快,我建议实施:


@Blaze%llu不是用于无符号long-long的正确选项吗?你试过调试这个问题吗?执行到底在哪里受阻?可能是计数或pom有问题,因为它们是整数,可能不够长,无法支持x超过13位?@NicoHaase它可以使用最大13位数字,但当输入数字超过13位时,它会冻结。例:输入215911504934497时冻结,例:12位1,有效,15位1,freezes@geekon对代码完全正确。它的效率非常低,因此需要非常、非常长的时间才能确定一个大数是否为素数。我不确定sqrt是否适用于大64位整数。@Jabberwocky-Hmm,但它适用于超过13位的数字是的,但我不确定它是否适用于17-18位数字。不过我没有调查。好吧,对你有好处。顺便说一句,你的图片不是证明,你应该看看,这是伟大的张贴像@Jabberwocky感谢你,不知道该网站的优化你所说的,你将不得不使用筛的Erathoneses详细介绍了我的网站answer@Samleo不确定,Erastothenes筛对于较小的值是很好的,但是对于较大的值,您只需要太多的内存。但是肯定还有更先进的算法,我们在这里使用的是非常幼稚和低效的算法,即使我做了一些改进。对于非常大的数字,你会遇到麻烦。在这里,您分配4GB内存,不确定这是否适用于大多数平台,而且当涉及大素数时,4294967296并不是一个很大的数字。是的,我知道您会遇到问题,这就是为什么我添加了二次优化,如果这个数太大,Erath的筛选不起作用。可能有一种方法可以解决内存问题,在更复杂的字符中使用单个位。所以你取一个整数,不把它看成是十进制整数,而是一个二进制数,每个位表示该数是否为素数的真与假
int is_prime(unsigned long long a)
{
    int i=0;
    int count=0;
    int test=0;
    int limit=sqrt(a)+1;
    if(a<=1)
        return 0;
    if(a==2)
        return 1;
    if(a%2==0)
        test=1;
    else
        for(i=3; i<limit && !test; i+=2, count++)
            if(a%i==0)
                test=1;
    if(!test)
        return 1;
    else
        return 0;
}
// long long integer square root found somewhere on the internet
unsigned long long isqrt(unsigned long long x)
{
  unsigned long long op, res, one;

  op = x;
  res = 0;

  /* "one" starts at the highest power of four <= than the argument. */
  one = 1LL << 62;  /* second-to-top bit set */
  while (one > op) one >>= 2;

  while (one != 0) {
    if (op >= res + one) {
      op -= res + one;
      res += one << 1;  // <-- faster than 2 * one  
    }
    res >>= 1;
    one >>= 2;
  }
  return res;
}


int is_prime(unsigned long long a)
{
  if (a <= 1 || a == 2 || a % 2 == 0)
    return 0;

  unsigned long long count = 0;
  unsigned long long limit = isqrt(a) + 1;

  for (unsigned long long p = 3; p < limit; p += 2)
  {
    if (a % p == 0)
      return 0;
  }
  return 1;
}
#define MAX_N 4294967296 //idk how big of an array your computer can actually handle. I'm using 2^32 here.

//Declare as a global variable for extra memory allocation
//unsigned char is used as it is only 1 byte (smallest possible memory alloc)
//0 for FALSE, 1 for TRUE.
unsigned char is_prime[MAX_N+1];

//Populate the is_prime function up to your input number (or MAX_N, whichever is smaller)
//This is done in O(N) time, where N is your number.
void performSieve(unsigned long long number){
    unsigned long long i,j;
    unsigned long long n = (number>MAX_N)?MAX_N:number; //quick way (ternary operator): "whichever is smaller"

    //Populating array with default as prime
    for(i=2; i<=n; i++) is_prime[i] = 1;

    for(i=4; i<=n; i+=2) is_prime[i] = 0; //all even numbers except 4 is not prime
    for(i=3; i<=n; i+=2){
        if(is_prime[i] == 1)
            for(j=i*i;j<=n;j+=i){ //all the multiples of i except i itself are NOT prime
                is_prime[i] == 0;
            }
    }    
}

//isPrime function
unsigned char isPrime(unsigned long long n){
    if(n<=1) return 0; //edge cases

    //Check if we can find the prime number in our gigantic sieve
    if(n<=MAX_N){
        return is_prime[n]; //this is O(1) time (constant time, VERY FAST!)
    }

    //Otherwise, we now use the standard "check all the divisors" method
    //with all the optimisations as suggested by previous users:
    if(n%2==0) return 0; //even number

    //This is from user @Jabberwocky
    unsigned long long limit = isqrt(a);

    for (unsigned long long p = 3; p <= limit; p += 2) {
        if (a % p == 0) return 0;
    }

    return 1;
}