My Program to calculate the largest prime factor of 600851475143, is stuck and never stops during compilation and execution. Does anyone know why it does not finish execution?
#include <stdio.h> //Edited the #includes(typo) to #include
int main (void)
{
long long int num = 600851475143 ;
long long int factorCount;
long long int bigFactor;
for ( long long int i=1 ; i <= num; i+=2 )// Iterating through all numbers from 2, smaller than or equal to num
{
if ( num % i == 0) // If the number "i" is a factor of num i.e. If "i" perfectly divides num
{
factorCount = 0;
//checking whether a factor "i" , is a prime factor of num
for ( long long int j=2; j <= i ; j++ ) // Iterating through all numbers from 2, smaller than or equal to "i"
{
if ( i % j == 0) // If the number "j" prefectly divides or is a factor of "i"
{
factorCount++; //Add 1 to factorCount
};
};
if ( factorCount == 1 ) // If factorCount has not exceeded 1 i.e., the number "i" is a prime number
{
bigFactor = i;
};
};
};
printf("The largets prime factor of %lli is %lli\n",num,bigFactor );
return 0;
}
I am not sure whether I understood your question .. so you just want to get the biggest prime factor for a certain number? If this is the case, then just do the following:
#include <stdio.h>
#define NUMBER 600851475143
int main (void)
{
long long int num = NUMBER;
long long int factor;
for (factor=2 ; num != 1; factor++) {
if (num % factor == 0) {
num = num / factor;
factor = factor-1;
}
}
printf("The largets prime factor of %lli is %lli\n",NUMBER, factor);
return 0;
}
Why this works: the first prime factor you find is the smallest prime factor of the number; the last prime factor is the biggest. Therefore once you have found a prime factor p, there does not exist a prime factor smaller than p, because otherwise you would have found that smaller prime factor before. Hence your next prime factor is greater equals p.
It finishes its execution, it just takes a lot of time.
You are performing a loop 600851475143 / 2 times or about 300 billion times. If the main loop takes 1ms to executes (but it should take more since there is another inner loop) then it means that time required would be about 9.5 years.
Just be patient and your loop will finish.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main (void)
{
long long int num = 600851475143 ;
long long int factorCount;
long long int bigFactor;
for ( long long int i=1 ; i <= sqrt(num); i+=2 )// Iterating through all numbers from 2, smaller than or equal to num
{
if ( num % i == 0) // If the number "i" is a factor of num i.e. If "i" perfectly divides num
{
factorCount = 0;
//checking whether a factor "i" , is a prime factor of num
for ( long long int j=2; j <= i ; j++ ) // Iterating through all numbers from 2, smaller than or equal to "i"
{
if ( i % j == 0) // If the number "j" prefectly divides or is a factor of "i"
{
factorCount++; //Add 1 to factorCount
};
};
if ( factorCount == 1 ) // If factorCount has not exceeded 1 i.e., the number "i" is a prime number
{
bigFactor = i;
};
};
};
printf("The largets prime factor of %lli is %lli\n",num,bigFactor );
return 0;
}
Only calcule the root of 600851475143.
Good Afternoon 24,
The runtime of this code will take very long, very very long. But it should work, only real error is the 's' in
#includes <stdio.h>
so just be patient, you're dealing with very large numbers, iterating through odd numbers has made it much less lengthy than it could be, don
Note: If you are using an online IDE such as cpp.sh or other source, the website will most likely time out. Please use a locally installed IDE.
Well, my best guess would be that it runs perfectly fine but takes too much time.
So what you have to do is optimize your algorithm.
Here are some hints for improving your algorithm:
You just need to iterate until the square root of a number to know whether or not it is a prime.
As you have done in our outer loop (but not in your inner loop), you just have to iterate through odd numbers.
Since you are looking for the highest prime factor, try beginning from the end and once you have reached a prime factor, stop looking.
I think that this should run in a reasonable amount of time.
EDIT: Actually, after reflexion the third point is not that obvious. Of course, it is better than going through all factors but the computation is way slower for large factors ...
This is reasonably efficient:
#include <stdio.h>
#define NUMBER 600851475143
static unsigned long long int gpf(unsigned long long n)
{
unsigned long long d, q;
while (n > 2 && !(n & 1))
n >>= 1;
d = 3;
while (d * d <= n) {
q = n / d;
if (q * d == n)
n = q;
else
d += 2;
}
return n;
}
int main(void)
{
printf("The largest prime factor of %llu is %llu\n",
NUMBER, gpf(NUMBER));
return 0;
}
Related
Given a range [ L , R ] (both inclusive), I have to tell find the maximum difference between two prime numbers in the given range. There are three answers possible for the given range.
If there is only one distinct prime number in the given range, then maximum difference in this case would be 0.
If there are no prime numbers in the given range, then output for this case would be -1.
Example:
Range: [ 1, 10 ]
The maximum difference between the prime numbers in the given range is 5.
Difference = 7 - 2 = 5
Range: [ 5, 5 ]
There is only one distinct prime number so the maximum difference would be 0.
Range: [ 8 , 10 ]
There is no prime number in the given range so the output for the given range would be -1.
Input Format
The first line of input consists of the number of test cases, T
Next T lines each consists of two space-separated integers, L and R
Constraints
1<= T <=10
2<= L<= R<=10^6
This is my code:
#include <stdio.h>
int isprime(int n)
{
int i,c=0;
for(i=1;i<n;i++)
{
if(n%i==0)
c++;
}
if(c==1)
return 1;
else
return 0;
}
int main()
{
int t; //testnumber
scanf("%d",&t);
for(int k=0;k<t;k++)
{
int l,r; //l=low or floor, r = highest range or ceiling;[l,r]
scanf("%d%d",&l,&r);
int n = r-l; //difference in range
int a[n];
int j=0;
for(int i=l;i<=r;i++)
{
if(isprime(i)==1)
{
a[j] = i;
j++;
}
}
int d = a[j-1]-a[0];
if(j==0)
printf("%d\n",-1);
else
printf("%d\n",d);
}
return 0;
}
When posting on a forum/stack or asking for review, try to name your variables appropriately. Otherwise, it becomes uneasy to follow the code or what is the purpose of which variable.
I wrote the code below hoping you will understand my implementation.
#include <iostream>
#include <math.h>
using namespace std;
void isPrime(int num, int* primeNumber)
{
if (num == 2)
{
*primeNumber = num; //2 is a prime number
return;
}
if (num%2 == 0)
{
return; //num is an even number, so, not prime
}
int limit = sqrt(num);
if (limit*limit == num)
{
return; //num is a square number, so, not prime
}
for (int i = 3; i <= limit; i=i+2)//to find if a number is prime or not, we only have to divide it from 2 to sqrt(num).
{ //i=i+2 skips even number, cause already checked if num is even or not.
if (num % i == 0)
{
return; //`num` is divisible by i, so, not prime
}
}
*primeNumber = num; //no divisible number found. so, num is prime.
}
int main()
{
int testNumber;
cout<< "Enter testNumber: ";
cin>> testNumber;
for (int i = 0; i < testNumber; ++i)
{
int newLow, low, high, lowestPrime = 0, highestPrime = -1;
cin>> low>> high;
newLow = low;
if (low == high)
{
cout<<"0\n";
continue;
}
for (int j = low; j <= high; ++j)//find the lowest prime
{
isPrime(j, &lowestPrime);
if (lowestPrime != 0)//if lowest prime found, lowestprime will no longer be 0
{
//cout<<"lowest prime: "<<lowestPrime<<endl;
newLow = j; //there is no prime number between low...newLow
break;
}
}
for (int j = high; j >= newLow; j--)//find highest prime
{
isPrime(j, &highestPrime);
if (highestPrime != -1)//if highest prime found, highestprime will no longer be -1
{
//cout<<"highest prime: "<<highestPrime<<endl;
break;
}
}
cout<<highestPrime - lowestPrime<<"\n";
}
return 0;
}
This task doesn't require any special algorithm(except checking if number is prime in O(sqrt(N))) to be solved efficiently. Think about prime numbers, what is the frequency of them on some range (for example on range from 1 to 100) what is some "pattern" that appears. Now, if i understood the task correctly you need to find maximal difference of primes on range which is last_prime_on_range - first_prime_on_range, from this and previous observation you can easily devise an efficient algorithm.
Spoiler:
You don't need to check whole range, it would be enough to check from L to L+100
and from R to R-100, obviously if L+100>R you can just go from L to R.
If you want to be sure you can go from L to L+1000 and from R to R-1000 since it doesn't impact time complexity too much.
Also, adding a break; when you find a prime would also solve the problem.
Note that this gap between primes is not guaranteed to be bellow 100/1000 but for given range checking up to 1000 would be enough.
Now if you need to check all primes in range, you should learn about Sieve Of Eratosthenes.
I am working in a math software with different features one of them to be to find all Carmichael numbers in a given interval [a,b)
This is my code, but I don't know if I have done it correctly or not cause I can't test it since the smallest Carmichael number is 560 which is too big for my pc to process.
#include <stdio.h>
int main() {
unsigned int begin, end;
printf("Write an int (begin):\n");
scanf("%d", &begin);
printf("Write an int (end):\n");
scanf("%d", &end);
int i;
for( int i=begin; i<end; i++ ) {
long unsigned int a_nr = i-1;
int a[a_nr];
for( int j=0; j<a_nr; j++ ) {
a[j] = j;
}
unsigned long c_nr[a_nr];
for( int k=0; k<a_nr; k++ ) {
unsigned long current_c_nr;
int mod;
for( int l=0; l<i; l++ ) {
current_c_nr= current_c_nr * a[k];
}
mod = current_c_nr%i;
if( mod==a[k] && mod!=a[k] ) {
c_nr[k] = i;
}
}
}
return 0;
}
If it is not correct, where is the mistake?
Thank you
P.S Overflow should be prevented.
When you say "This is my code, but I don't know if I have done it correctly or not cause I can't test it since the smallest Carmichael number is 560 which is too big for my pc to process" then the conclusion is -- you haven't done it correctly. You should be able to process 561 (560 must be a typo) in a small fraction of a second. Even if your algorithm is in principle correct, if it can't handle the smallest Carmichael number then it is useless.
n is Carmichael if and only if it is composite and, for all a with 1 < a < n which are relatively prime to n, the congruence a^(n-1) = 1 (mod n) holds. To use this definition directly, you need:
1) An efficient way to test if a and n are relatively prime
2) An efficient way to compute a^(n-1) (mod n)
For the first -- use the Euclidean algorithm for greatest common divisors. It is most efficiently computed in a loop, but can also be defined via the simple recurrence gcd(a,b) = gcd(b,a%b) with basis gcd(a,0) = a. In C this is just:
unsigned int gcd(unsigned int a, unsigned int b){
return b == 0? a : gcd(b, a%b);
}
For the second point -- almost the worst possible thing you can do when computing a^k (mod n) is to first compute a^k via repeated multiplication and to then mod the result by n. Instead -- use exponentiation by squaring, taking the remainder (mod n) at intermediate stages. It is a divide-and-conquer algorithm based on the observation that e.g. a^10 = (a^5)^2 and a^11 = (a^5)^2 * a. A simple C implementation is:
unsigned int modexp(unsigned int a, unsigned int p, unsigned int n){
unsigned long long b;
switch(p){
case 0:
return 1;
case 1:
return a%n;
default:
b = modexp(a,p/2,n);
b = (b*b) % n;
if(p%2 == 1) b = (b*a) % n;
return b;
}
}
Note the use of unsigned long long to guard against overflow in the calculation of b*b.
To test if n is Carmichael, you might as well first test if n is even and return 0 in that case. Otherwise, step through numbers, a, in the range 2 to n-1. First check if gcd(a,n) == 1 Note that if n is composite then you must have at least one a before you reach the square root of n with gcd(a,n) > 1). Keep a Boolean flag which keeps track of whether or not such an a has been encountered and if you exceed the square root without finding such an a, return 0. For those a with gcd(a,n) == 1, compute the modular exponentiation a^(n-1) (mod n). If this is ever different from 1, return 0. If your loop finishes checking all a below n without returning 0, then the number is Carmichael, so return 1. An implementation is:
int is_carmichael(unsigned int n){
int a,s;
int factor_found = 0;
if (n%2 == 0) return 0;
//else:
s = sqrt(n);
a = 2;
while(a < n){
if(a > s && !factor_found){
return 0;
}
if(gcd(a,n) > 1){
factor_found = 1;
}
else{
if(modexp(a,n-1,n) != 1){
return 0;
}
}
a++;
}
return 1; //anything that survives to here is a carmichael
}
A simple driver program:
int main(void){
unsigned int n;
for(n = 2; n < 100000; n ++){
if(is_carmichael(n)) printf("%u\n",n);
}
return 0;
}
output:
C:\Programs>gcc carmichael.c
C:\Programs>a
561
1105
1729
2465
2821
6601
8911
10585
15841
29341
41041
46657
52633
62745
63973
75361
This only takes about 2 seconds to run and matches the initial part of this list.
This is probably a somewhat practical method for checking if numbers up to a million or so are Carmichael numbers. For larger numbers, you should probably get yourself a good factoring algorithm and use Korseldt's criterion as described in the Wikipedia entry on Carmichael numbers.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int anz;
scanf("%d", &anz);
time_t start = time(0);
int *primZ = malloc(anz * sizeof(int));
primZ[0] = 2;
int Num = 0;
for (int i = 1, num = 3; i < anz; num += 2) {
for (int j = 1; j < i; j++) {
if (num % primZ[j] == 0) {
num += 2;
j = 0;
}
//this part
if (primZ[j] > i / 2)
break;
}
primZ[i] = num;
i++;
printf("%d ,",num);
}
time_t delta = time(0) - start;
printf("%d", delta);
getchar();
getchar();
return 0;
}
The code works perfectly fine, the question is why. The part if(primZ[j] > i/2) makes the program 2 - 3 times faster. It was actually meant to be if(primZ[j] > num/3) which makes perfect sense because num can only be an odd number. But it is the number of found prime numbers. It makes no sense to me. Please explain.
You check if the prime is composite by checking if it divisible by already found prime numbers. But in doing so you only have to check up to and including the square root of the number because any number larger than that that divides the number will leave a smaller number than the square root of the number.
For example 33 is composite, but you only have to check numbers up to 5 to realize that, you don't need to check it being divisible by 11 because it leaves 3 (33/11=3) which we already checked.
This means that you could improve your algorithm by
for (int j = 1; j < i; j++) {
if( primZ[j]*primZ[j] > num )
break;
if (num % primZ[j] == 0) {
num += 2;
j = 0;
}
}
The reason you can get away with comparing with cutting of at i/2 is due to the distribution of the prime numbers. The prime counting function is approximately i = num/log(num) and then you get that i/2 > sqrt(num).
The reason is that the actual bound is much tighter than num/3 - you could use:
if (primZ[j] > sqrt(num))
The reason for that being that if a prime higher than the square root of num divides num, there must also be a lower prime that does (since the result of such a division must be lower than the square root).
This means that as long as i/2 is higher than sqrt(num), the code will work. What happens is that the number of primes lower than a number grows faster than the square root of that number, meaning that (completely accidentally) i/2 is a safe bound to use.
You can check out how your i value behaves here - they call it pi(x), the number of primes less than x.
It makes sense, since if n has two factors one of them is surely less than or equal to n/2, sense the program found no factors of i in primZ that are less than or equal to i/2 it means there's no factors of i -except 1 of course-.
Sense primZ is sorted in ascending order and j only increases, when primeZ[j] > i/2 it indicates that there's no factors of i in primZ that are less than i/2.
P.S.The point of starting the search is stated in the first part of the for statement num=3 , and the recurring statement num += 2 ensures you only test odd numbers
I'm trying to answer this question:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
Here is my code:
#include <stdio.h>
int isPrime(long long num)
{
for (long long k = 1; k < num; k++)
{
if (num%k == 0)
return 0;
}
return 1;
}
long long num = 600851475143;
int main(void)
{
long long prime_factor = 0;
for (long long j = 2; j < num; j++)
{
if (num % j == 0 && isPrime(j) == 1)
prime_factor = j;
}
printf("%lli\n", prime_factor);
}
But for some reason it doesn't print anything, or even end. What is causing this?
That's a terribly inefficient way of finding the prime factors of a number.
To find the prime factors, you should:
Create a static list of primes less than or equal to (number / 2).
Iterate over each element in the list of primes and see if each
one can evenly divide the number.
Divide the original number by the prime, and check the last number
again.
Why? Well the smallest prime is 2. If the number isn't even then the first prime that can divide any number > 2 is 3.
Every number can be uniquely identified by its prime factors. This is called the Fundamental Theorem of Arithmetic. That means that there is only one way to represent e.g. 15 as a product of primes, in this case { 3, 5 }.
However any prime can divide a number more than once. For example, 49 is the product of two primes { 7, 7 }. Dividing the original number by one of its factors makes subsequent divisions quicker. And you can logically stop checking when the number == 1.
It doesn't print anything because it never leaves the loop, after which is found the only line which prints anything in the code. Try a smaller number and see if it ends.
This is a program to count the number of divisors for a number, but it is giving one less divisor than there actually is for that number.
#include <stdio.h>
int i = 20;
int divisor;
int total;
int main()
{
for (divisor = 1; divisor <= i; divisor++)
{
if ((i % divisor == 0) && (i != divisor))
{
total = total++;
}
}
printf("%d %d\n", i, total);
return 0;
}
The number 20 has 6 divisors, but the program says that there are 5 divisors.
&& (i != divisor)
means that 20 won't be considered a divisor. If you want it to be considered, ditch that bit of code, and you'll get the whole set, {1, 2, 4, 5, 10, 20}.
Even if you didn't want the number counted as a divisor, you could still ditch that code and just use < instead of <= in the for statement.
And:
total = total++;
is totally unnecessary. It may even be undefined, I'm just too lazy to check at the moment and it's not important since nobody writes code like that for long :-)
Use either:
total = total + 1;
or (better):
total++;
Divisor counting is perhaps simpler and certainly faster than any of these. The key fact to note is that if p is a divisor of n, then so is n/p. Whenever p is not the square root of n, then you get TWO divisors per division test, not one.
int divcount(int n)
{
int i, j, count=0;
for (i=1, j=n; i<j; j = n/++i)
{
if (i*j == n)
count += 2;
}
if (i == j && i*j == n)
++count;
return count;
}
That gets the job done with sqrt(n) divisions, and sqrt(n) multiplications. I choose that because, while j=n/i and another j%i can be done with a single division instruction on most CPUs, I haven't seen compilers pick up on that optimization. Since multiplication is single-clock on modern desktop processors, the i*j == n test is much cheaper than a second division.
PS: If you need a list of divisors, they come up in the loop as i and j values, and perhaps as the i==j==sqrt(n) value at the end, if n is a square.
You have added an extra check && (i != divisor) as explained in given answer.
Here, I wrote the same program using the prime factorisation. This is quick way to find the number of divisor for large number (reference).
// this function return the number of divisor for n.
// if n = (m^a) (n^b) ... where m, n.. are prime factors of n
// then number of divisor d(n) = (a+1)*(b+1)..
int divisorcount(int n){
int divider = 2;
int limit = n/2;
int divisorCount = 1;
int power = 0;
// loop through i=2...n/2
while(divider<=limit){
if(n%divider==0){
// dividing numper using prime factor
// (as smallest number devide a number
// is it's prime factor) and increase the
// power term for prime factor.
power++;
n/=divider;
}
else{
if(power != 0){
// use the prime factor count to calculate
// divisor count.
divisorCount*=(power+1);
}
power = 0;
divider++;
// if n become 1 then we have completed the
// prime factorization of n.
if(n==1){
break;
}
}
}
return divisorCount;
}