Printing the Largest Prime Factor of a Composite Number in C - c

I was solving a puzzle, where im required to find the largest Prime Factor of a composite number entered by the user.
I thought of something and have tried it out, but it doesn't manage to detect the largest prime factor amongst the factors of the composite number.
I'm appending my code below, I'd be grateful if anyone could help me out here to get to detect the largest prime no. amongst the factors and print it.
// Accept a composite number from user and print its largest prime factor.
#include<stdio.h>
void main()
{
int i,j,b=2,c;
printf("\nEnter a composite number: ");
scanf("%d", &c);
printf("Factors: ");
for(i=1; i<=c/2; i++)
{
if(c%i==0)
{
printf("%d ", i);
for(j=2; j<=i/2; j++) //since a numbr cand be divisible by a number greated than its half
{ if(i%j > 0)
b = i;
else if(i==3)
b = 3;
}
}
}
printf("%d\nLargest prime factor: %d\n", c, b);
}

The trick is, find the smallest prime factor, and divide the composite number c by it to obtain the largest prime factor.
The trick is to find the smallest factor F (starting from 2) where C / F is prime. Then, C / F will be the largest prime factor of C.
Edit: It looks like you also want to list all the factors. The problem is, in your inner loop that tests for primality, you set the largest prime to i for numbers that are divisible with anything. In other words, try something like this:
is_prime = true;
for (j = 2; j <= x / 2; j++) {
if (i % j == 0)
is_prime = false;
}
if (is_prime)
largest_prime = x;
Note that you could actually stop sooner than x divided by 2. You could stop at the square root of x. However, the sqrt() function in <math.h> is a bit messy to work with in your case because it works with floating point numbers, not integers.

To find the prime factorization, you'd normally find all the factors between 2 and sqrt(N). You'd divide the composite by each of those to obtain the rest of the factors. Then recurse to find the prime factors of each of those.
When you're done, you'll have a list of all the prime factors. Getting the largest item in the list should be fairly trivial.

In your inner loop, you're setting b = i if there does exist a number that isn't a factor of i. You need to set b = i if there doesn't exist a number that is a factor of i.
(by "number", I mean "an integer between 2 and sqrt(i)" of course)

Factorization is a classic number theory problem. You can find many factorization algorithms in number theory textbooks. Some of them are available on wiki http://en.wikipedia.org/wiki/Integer_factorization

Hey thanks for the input friends, i worked out something and now the program prints the greatest prime factor of the composite number ,provided that the composite number is lesser than 52, while for higher ranges above this, it doesn't print the right output.
I'm Appending the code, please see if you guys could help me around
#include<stdio.h>
void main()
{
int i,j,b=2,c;
printf("\nEnter a composite number: ");
scanf("%d", &c);
printf("Factors: ");
for(i=1; i<=c/2; i++)
{
if(c%i==0)
{
printf("%d ", i);
for(j=1; j<=i; j++) //since a numbr cand be divisible by a number greated than its half
{ if(i%j > 0)
b = i; //b stores the largest prime factor
if(b%3==0)
b = 3;
else if(b%2==0)
b=2;
else if(b%5==0)
b=5;
}
}
}
printf("%d\nLargest prime factor: %d\n", c, b);
}

In Python, Something like this will do:
import math
import itertools
# largest prime factor of a composite number
def primality(num):
for i in range(2,int(math.sqrt(num))+1):
if num%i ==0:
return 0
return 1
if __name__ == '__main__':
number = 600851475143
for i in itertools.count(2,1):
if number%i == 0:
if number%10 in [7,9,1,3] and primality(number/i):
print number/i
break
What I have done to check primality is the neat square root technique.

Related

How to optimize/ make this c code even faster?

I need to optimize this c code in order for it to run as fast as possible. I am quite new to code optimization in general. What should I begin with?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char*argv[]) {
int n, i, flag;
int sumOfPrimeNumbers; //sum of prime numbers
sumOfPrimeNumbers = 0;
do {
flag = 0;
scanf("%d", &n);
for(i=2;i < n;i++)
{
if(n%i==0) {
flag=1; // flag all non-prime numbers
break;
}
}
if(flag==0) {
sumOfPrimeNumbers = sumOfPrimeNumbers + n; // sum prime numbers
}
} while (n != 0);
printf("%d\n", sumOfPrimeNumbers);
return 0;
}
For small values of n (maybe values less than 66536?) you can use a table of precomputed answers, like "printf("%d\n", table[n]);".
For larger values you can split n into "zone" and "offset in zone", like "zone = n / zone_size; offset = n % zone_size;" and then use "zone" as an index into a precomputed table to determine an initial starting point (and skip a huge amount of work, like "sumOfPrimeNumbers = zoneStartTable[n / zone_size;"). The "offset in zone" part can be used with Sieve of Eratosthenes; which means that it's nicer for "zone_size" to be the product of the smallest primes (e.g. maybe like "zone_size = 2 * 3 * 5 * 7 * 11 * 13 * 17;") because that makes it a little easier to create a Sieve of Eratosthenes from a non-zero starting point.
For this approach to work you will actually need 2 sieves - one to find primes from 1 to "sqrt(n)" so that you can mark multiples of those primes as "not prime" in the second sieve (which will contain values from "zone * zone_size" to n). This process can be accelerated by recognizing that the sieve for the smallest primes (that you used to determine "zone_size") create a pattern that repeats every "zone_size" numbers, and that pattern can be predetermined and then copied into both of the sieves to initialize the sieves, allowing you to skip marking the smallest primes in both sieves.
Improve the algorithm. Avoid premature optimizations
Rather than test up to n, search to the square root of n
// for(i=2;i < n;i++)
for (i=2; i <= n/i; i++)
Sieve of Eratosthenes
Form a list of found primes {2,3,5} and only test against those. As a new prime is found, append it to the list.
Many other optimizations possible.

how to write a function that prints out mean value of prime numbers in c

I'm trying to solve a problem, where I am supposed to write a function that prints out the mean value of all prime numbers between 2 and N but I don't know how to start. I have already written a function that prints out all the prime numbers.
sum the prime numbers as you find them instead of printing
also count the number of primes you found
then divide the sum by number of primes
for example, assuming you have written the function for prime :
count=0;
for(i=2;i<n;i++) {
if(isPrime(i)) {
sum+=i;
count++;
}
}
mean = sum/count; // watch for integer division

Finding Largest Twin Prime

I am trying to create a c program which prompts for user input and then, finds the largest twin prime within that number. This program then loops continuously, prompting the user for an input again and again and finding the largest twin prime until the user enters -1, after which it terminates. I wrote down the basic code, but have yet been able to make it loop continuously when using certain numbers such as 20 and 65. I cannot figure out what is wrong with my code.
I seem to be having another problem as well. For 20, the values show (15,17) instead of (17,19). Obviously the logic is wrong somewhere but I am not sure exactly where either.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<conio.h>
int prime(int x)
{
int i,numroot;
numroot=sqrt(x);
for(i=2;i<=numroot;i++)
if(x%i==0){
return(0);
}
return(1);
}
int main()
{
double N;
printf("This program prints out all the possible twin primes until a specific number which...\nyou can choose!");
printf("\nA note of caution: Although this program accepts decimals, the value entered must be between 5 and 10^9,inclusive of the 2 numbers.");
printf("\nKey in -1 to exit.");
printf("\nEnter N value upto which twin primes ought to be calculated until: ");
scanf("%lf",&N);
while (N!=-1) {
if (N<5 || N>pow(10,9)) {
printf("\nNumber not in the valid range was inputted. \nPlease reenter the value: ");
scanf("%lf",&N);
}
else {
int n;
n=floor(N);
int prime(int x);
int f,originalval;
originalval=N;
f=prime(n);
while(f==0){//Calculates for largest prime number below user input
n--;
f=prime(n);
}
int smallint=n-2;
while(prime(smallint)==1){
n--;
f=prime(n);
while(f==0){
n--;
f=prime(n);
}
int smallint=n-2;
}
printf("The largest twin prime pair not above %d is (%d,%d)",originalval,smallint,n);
printf("\nPlease re-enter the value:");
scanf("%lf",&N);
}
}
printf("\nProgram successfully terminated.");
return 0;
}
You are doing a research about prime numbers "upto" a given number N.
In this class of problems is more efficient (although more expensive in RAM space) to store information in tables of primes and composite numbers, like the Sieve of Eratosthenes.
Once you have filled the table with the information of which numbers are prime and composite, it's just a matter of iterate on the table to look for the twin primes, wherever they are.
However, although you inform to the user that all the twin primes will be shown, actually what your program does is trying to show only the lastest.
Please, have clear which is the goal of your program.
On the other hand, you are redefining the identifier smallint inside the innest loop, which is, for sure, a logical error.
In case you cannot use arrays to store the Sieve of Eratosthenes, then I show you here a method that is not hard to implement (but it's not, of course, the most efficient; however it will avoid a lot of redundant computations).
The twin primes (greater than 4) can be of two different forms:
6k-1, 6k+1
6k+1, 6k+5
So, I would jump in the sequence of numbers having the form 6k+1, 6k+5, for k = 0, 1, 2, 3, ..., so that I only would analyze the odd numbers in the sequence:
5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, ...
This can be obtained by adding 2, then 4, then 2, then 4, then 2, then 4...
So, one can take the first pair, let's say 5 and 7.
We divide both of them by the odd numbers of the form 6k+1 and 6k+5 less than the square root of the greatest of them (sqrt(7)).
If the less number (in this case 5) would be divisible by some number, we pick the following number in the list, which is 11, and divide it by all the numbers that were used so far to test if 7 is prime or not. From this point, we follow by dividing together, 7 and 11, by the remaining numbers up to sqrt(11), and so on.
Note that, for big numbers, 6k+1 and 6k+5 have very similar square roots.
If the opposite case happens, that is, that for the pair (5, 7), the biggest element of the couple (in this case: 7) is divisible by some other number, then we discard both of them (5 and 7) and pick the following two elementos of the list (in this example would be 11 and 13). So, we start the search from scratch (that is, by dividing by small numbers).
finally, if the loop ends without finding divisors for any element of the couple (which is indeed the case for 6 and 7), then we can inform that this couple is of twin primes.
(Or well we can keep silent).
Then, we discard the smallest element (in this case: 5) and retain the biggest element (in this case: 7).
Since we already know that 7 is prime, we only pick the following element of the list above (in this case, 11), and search for divisors of it, only.
I think that the method I have explained will avoid to you a lot of redundant computations.
Besides, it's necessary to keep the latest updated couple of twin primes found. I assume that is not necessary that I explain to you how to do that.
We should procure that both of numbers are prime. Between difference is 2. As you know first twin prime is (3,5). I haven't found a formula what I expected. So, I've used iteration for solution. If you look through the code, you can understand.
#include <stdio.h>
#include <math.h>
int twinPrime(int m);
int IsPrime(unsigned int number);
int main()
{
double N;
int floored;
int prime;
printf("This program prints out all the possible twin primes"
"until a specific number which...\nyou can choose!");
printf("\nA note of caution: Although this program accepts decimals, "
"the value entered must be between 5 and 10^9,inclusive of the 2 numbers.");
printf("\nKey in -1 to exit.");
printf("\nEnter N value upto which twin primes ought to be calculated until: ");
scanf("%lf",&N);
while (N != -1)
{
if (N < 5 || N > pow(10,9))
{
printf("\nNumber not in the valid range was inputted. \n"
"Please reenter the value: ");
scanf("%lf",&N);
}
else
{
floored = floor(N);
prime = twinPrime(floored);
printf("The largest twin prime pair not above %d is (%d,%d)",floored,prime - 2,prime);
printf("\nPlease re-enter the value:");
scanf("%lf",&N);
}
}
printf("\nProgram successfully terminated.");
return 0;
}
int twinPrime(int m)
{
int p = 3;
int q = 5;
for (; q < m - 1; q += 2)
{
if (IsPrime(q))
{
if (q - p == 2)
{
continue;
}
p = q;
}
}
return q;
}
int IsPrime(unsigned int number)
{
if (number <= 1) return 0; // zero and one are not prime
if ((number > 2) && ((number % 2) == 0)) return 0; //no even number is prime number (bar 2)
unsigned int i;
for (i=2; i*i<=number; i++)
{
if (number % i == 0) return 0;
}
return 1;
}

C prime factorization (loop failure?)

I've been looking into this simple piece of code for 1.5 hrs now and do not find the mistake. I start going crazy ;)
Could anyone of you with a fresh mind and view give me a little hint, where I might have the mistake in? (I am relatively new to C)
The problem is: The code works fine for most of the numbers I entered and tested, but accidentically I found a number that does not work: 3486118 (or 55777888 which is a multiple of it) It goes right for the first loop(s), but after factor 2 it becomes an endless loop.
Here is my code: (any help is greatly appreciated)
// Program calculates prime factors of entered number and returns them
#include <stdio.h>
int main() {
long int num, num_cp;
long int product=1;
/*prime number array up to 100.000*/
long int prime[] = {2, 3, **[...cut out MANY numbers...]** 99971, 99989, 99991};
printf("Please enter a positive integer:\n");
scanf("%li", &num);//55777888 or 3486118 not working... why?
//copy the entered number to keep the original for comparison with "product" and "break;" if equal
num_cp=num;
printf("prime factorization of %li:\n\n", num);
for (int i=0; i<sizeof(prime); i++) {
if (num_cp%prime[i]==0) {
num_cp/=prime[i];
product*=prime[i];
if (product==num) {
printf("%li\n\n", prime[i]);
break;
}
printf("%li*", prime[i]);
//If prime factor found but "product" is still not equal to "num" reset loop counter "i" to -1 (==0 in next loop)
i=-1;
}
}
printf("END");
return 0;
}
"I've been looking into this simple piece of code for 1.5 hrs now and do not find the mistake. I start going crazy ;)"
Don't. Leave it. Go away and eat a pizza. Veg out in front of your favourite movie. Have a shower. Aim for a new high-score on 2048 (or whatever). Your brain gets stuck in a rut and you are no longer seeing your code. You are only seeing what you think your code is.
When you get your brain out of the rut, then -- and only then -- go back and actually read the code you wrote. Not the code you think you wrote, but the code you actually wrote. Yes, they are different.
The prime factors of 55777888 are 2·2·2·2·2·1743059, where the last factor is too large to be contained in your list.
You can fix this in your code: When the product is equal to the product of the prime factors you have found, num_cp is 1. If num_cp is greater than one after you have exhausted your prime list, it is a factor of num. If num/num_cp is smaller than the largest prime you have checked, you can assume that the remaining value of num_cp is a prime. If it wasn't you'd have found more factors earlier.
You can fix this by adding an additional check after your main loop:
if (num_cp > 1) printf("%li\n\n", num_cp);
(If long int is a 64-bit number on your system, you're still not safe: The remaining factor might be made up of several numbers that are not in your array.)
Finally: Resetting the for loop counter so that the loop starts over isn't a good idea. It always starts from the beginning and re-checks primes that you have already checked. And it just isn't natural program flow, which makes it hard to read. A while loop instead of the inner if block would be more natural in my opinion.
Edit: To illustrate:
#include <stdio.h>
int main() {
long int num;
/* prime number array up to 100.000 */
long int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
int nprime = sizeof(prime) / sizeof(*prime);
num = 55;
printf("%li == ", num);
for (int i = 0; i < nprime; i++) {
long int p = prime[i];
if (num <= 1) break;
while (num % p == 0) {
num /= prime[i];
printf("%li", p);
if (num > 1) printf(" * ");
}
}
if (num > 1) printf("%li", num);
printf("\n");
return 0;
}
Things to note:
Instead of resetting the main loop counter i, a while loop is used, which consumes all repetitions of the same factor. If a prime p doesn't divide the number, the while loop isn't entered, just like an if clause.
I've removed the copy of num and used num throughout, mainly to remove clutter. I've also removed the product. Your logic that all prime factors should multiply to the original number, is good. But it also works the other way round: After dividing the number by all primes, we are left with 1. And we have to divide the number anyways. By removing the product, we have to keep track of only one variable instead of two.
I've moved the break condition to the front, so we catch negative numbers and 0 early.
That said, your way to code isn't wrong, just maybe a bit unusual in places.

Write a program that sums the sequence of integers, as well as the smallest in the sequence

Write a program that sums the sequence
of integers as well as the smallest in
the sequence. Assume that the first
integer read with scanf specifies the
number of values remaining to be
entered. For example the sequence
entered:
Input: 5 100 350 400 550 678
Output: The sum of the sequence of
integers is: 2078
Input: 5 40 67 9 13 98
Output: The smallest of the integers
entered is: 9
This is a daily problem I am working on but by looking at this, Isnt 5 the smallest integer? I have no idea how to write this program. Appreciate any help
First thing, the 5 is not considered part of the list, it's the count for the list. Hence it shouldn't be included in the calculations.
Since this is homework, here's the pseudo-code. Your job is to understand the pseudo-code first (run it through your head with sample inputs) then turn this into C code and try to get it compiling and running successfully (with those same sample inputs).
I would suggest the sample input of "2 7 3" (two items, those being 7 and 3) as a good start point since it's small and the sum will be 10, smallest 3.
If you've tried to do that for more than a day, then post your code into this question as an edit and we'll see what we can do to help you out.
get a number into quantity
set sum to zero
loop varying index from 1 to quantity
get a number into value
add value to sum
if index is 1
set smallest to value
else
if value is less than smallest
set smallest to value
endif
endif
endloop
output "The sum of the sequence of integers is: ", sum
output "The smallest of the integers entered is: ", smallest
Stack Overflow seems to be divided into three camps, those that will just give you the code, those that will tell you to push off and do your own homework and those, like me, who would rather see you educated - by the time you hit the workforce, I hope to be retired so you won't be competing with me :-).
And before anyone picks holes in my algorithm, this is for education. I've left at least one gotcha in it to help train the guy - there may be others and I will claim I put them there intentionally to test him :-).
Update:
Robert, after your (very good) attempt which I've already commented on, this is how I'd modify your code to do the task (hand yours in of course, not mine). You can hopefully see how my comments modify the code to reach this solution:
#include <stdio.h>
int main (int argCount, char *argVal[]) {
int i; // General purpose counter.
int smallNum; // Holds the smallest number.
int numSum; // Holds the sum of all numbers.
int currentNum; // Holds the current number.
int numCount; // Holds the count of numbers.
// Get count of numbers and make sure it's in range 1 through 50.
printf ("How many numbers will be entered (max 50)? ");
scanf ("%d", &numCount);
if ((numCount < 1) || (numCount > 50)) {
printf ("Invalid count of %d.\n", numCount);
return 1;
}
printf("\nEnter %d numbers then press enter after each entry:\n",
numCount);
// Set initial sum to zero, numbers will be added to this.
numSum = 0;
// Loop, getting and processing all numbers.
for (i = 0; i < numCount; i++) {
// Get the number.
printf("%2d> ", i+1);
scanf("%d", &currentNum);
// Add the number to sum.
numSum += currentNum;
// First number entered is always lowest.
if (i == 0) {
smallNum = currentNum;
} else {
// Replace if current is smaller.
if (currentNum < smallNum) {
smallNum = currentNum;
}
}
}
// Output results.
printf ("The sum of the numbers is: %d\n", numSum);
printf ("The smallest number is: %d\n", smallNum);
return 0;
}
And here is the output from your sample data:
pax> ./qq
How many numbers will be entered (max 50)? 5
Enter 5 numbers then press enter after each entry:
1> 100
2> 350
3> 400
4> 550
5> 678
The sum of the numbers is: 2078
The smallest number is: 100
pax> ./qq
How many numbers will be entered (max 50)? 5
Enter 5 numbers then press enter after each entry:
1> 40
2> 67
3> 9
4> 13
5> 98
The sum of the numbers is: 227
The smallest number is: 9
pax> ./qq
How many numbers will be entered (max 50)? 0
Invalid count of 0.
[fury]$ ./qq
How many numbers will be entered (max 50)? 51
Invalid count of 51.
By the way, make sure you always add comments to your code. Educators love that sort of stuff. So do developers that have to try to understand your code 10 years into the future.
Read:
Assume that the first integer read
with scanf specifies the number of
values remaining to be entered
so it's not part of the sequence...
for the rest, it's your homework (and C...)
No. 5 is the number of integers you have to read into the list.
Jeebus, I'm not doing your homework for you, but...
Have you stopped to scratch this out on paper and work out how it should work? Write some pseudo-code and then transcribe to real code. I'd have thought:
Read integer
Loop that many times
** Read more integers
** Add
** Find Smallest
IF you're in C look at INT_MAX - that will help out finding the smallest integer.
Since the list of integers is variable, I'd be tempted to use strtok to split the string up into individual strings (separate by space) and then atoi to convert each number and sum or find minimum on the fly.
-Adam
First you read the number of values (ie. 5), then create an array of int of 5 elements, read the rest of the input, split them and put them in the array (after converting them to integers).
Then do a loop on the array to get the sum of to find the smallest value.
Hope that helps
wasn[']t looking for you guys to do the work
Cool. People tend to take offense when you dump the problem text at them and the problem text is phrased in an imperative form ("do this! write that! etc.").
You may want to say something like "I'm stuck with a homework problem. Here's the problem: write a [...]. I don't understand why [...]."
#include <stdio.h>
main ()
{
int num1, num2, num3, num4, num5, num6, i;
int smallestnumber=0;
int sum=0;
int numbers[50];
int count;
num1 = 0;
num2 = 0;
num3 = 0;
num4 = 0;
num5 = 0;
num6 = 0;
printf("How many numbers will be entered (max 50)? ");
scanf("%d", &count);
printf("\nEnter %d numbers then press enter after each entry: \n", count);
for (i=0; i < count; i++) {
printf("%2d> ", i+1);
scanf("%d", &numbers[i]);
sum += numbers[i];
}
smallestnumber = numbers[0];
for (i=0; i < count; i++) {
if ( numbers[i] < smallestnumber)
{
smallestnumber = numbers[i];
}
}
printf("the sum of the numbers is: %d\n", sum);
printf("The smallest number is: %d", smallestnumber);
}

Resources