在用户输入的数字-C中查找最大素数
我的代码有问题。本课题是编写一个C程序,在用户输入的数字中找出最大素数 例: 输入号码:46656665326 产出:66566653 这是我的代码:在用户输入的数字-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
#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;
}