Performance issue in c while dealing with 12 digit number - c

currently i am working on a program. program is working perfectly but it has performance issue. the code is below.
#include<stdio.h>
int calculate(int temp)
{
int flag = 0,i = 2,tmp = 0;
for(i = 2;i < temp;i++)
{
if(temp % i == 0)
{
return 1;
}
}
}
int main()
{
long int i = 2,j,count = 0,n = 600851475143,flag = 0,prime = 0;
long int check;
while(i < n)
{
if(n % i == 0)
{
check = calculate(i);
if(check != 1)
{
prime = i;
printf(" Prime number is : %ld \n", prime);
}
}
i++;
}
printf(" Max prime number of %ld is : %ld \n",n,prime);
return 0;
}
I can't able to get the maximum prime number here.
can anyone tell me what should i do it takes too much time what should i do to get output fast?

If you are looking for a maximum prime, why are you starting at 2? Begin checking at n and work backwards
calculate can run faster since you only need to check for a divisor up to sqrt(temp), if it has a divisor larger than that, it also has a divisor smaller than that.
Your loop increments and decrements can be done in hops of 2. So you'd also halve the range of numbers to check.
Calling printf in the middle of a search loop for when the check fails is just a waste of execution speed. Instead, check for success and break out of the loop.
With these modifications in mind (and your code cleaned from a lot of UB):
#include<stdio.h>
int calculate(long int temp)
{
long int flag = 0,i = 2,tmp = 0;
if (temp % 2 == 0)
return 1;
for(i = 3; i*i <= temp; i+=2)
{
if(temp % i == 0)
{
return 1;
}
}
return 0;
}
int main(void)
{
long int j, count = 0, n = 600851475143, i = n, flag = 0, prime = 0;
long int check;
while(i > 0)
{
if(n % i == 0)
{
check = calculate(i);
if(check)
{
prime = i;
break;
}
}
i-=2;
}
printf(" Max prime number of %ld is : %ld \n",n,prime);
return 0;
}

Related

Prime printing. Ask for point out errors in the code

Put all the prime numbers of lim in the aa array.
This function returns the number of the obtained prime numbers, and finally prints these prime numbers.
Here is my code.
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
#define MAX 100
int func(int lim,int aa[MAX])
{
int i,count,num;
num = 0;
for(count = 2;count<lim;count++)
{
for(i=2;i<=sqrt(count);i++)
{
if(count%i==0)
break;
}
if(i>sqrt(count))
{
aa[num]=i;
num++;
}
}
return num;
}
int main()
{
int limit,i,sum;
int aa[MAX];
printf("Please input an integer:");
scanf("%d",&limit);
sum=func(limit,aa);
for(i=0;i<sum;i++)
{
if(i%10==0&&i!=0)
printf("\n");
printf("%5d",aa[i]);
}
return 0;
}
Unfortunately, the results I got when I ran the program did not meet the expectations.
The error is that every run results have a 2 in the first place and loss the last number
e.g.
And it should be 2 3 5.
Avoid floating point math for an integer problem
Do not use sqrt().
// for(i=2;i<=sqrt(count);i++)
for(i = 2; i <= count/i; i++)
Do not iterate once MAX values found
aa[num]=i;
num++;
if (num == MAX) return num; //add
I'd recommend an isprime() helper function to simplify code.
int isprime(int num) {
if (num % 2 == 0)
return num == 2;
for (int divisor = 3; divisor <= num / divisor; divisor += 2) {
if (num % divisor == 0)
return 0;
}
return num > 1;
}
int func(int lim, int aa[MAX]) {
size_t prime_index = 0;
for(int prime_candidate = 2; prime_candidate <= lim; prime_candidate++) {
if (isprime(prime_candidate)) {
aa[num] = prime_candidate;
num++;
if (num == MAX) break;
}
}
return num;
}

How to find the nth number?

For an assignment, I have to write code which accepts as input an integer n and outputs the nth 'superunusual' number.
The first few su-numbers are: 22, 23, 26, 33, ... So when the input is 1, the output should be 22. 2 gives 23 and 3 gives 26.
I already have a code that checks if the input number is a su-number, but I can't find a way to calculate the nth number.
So when I now input 22, it says that 22 is a superunusual number.
The code:
/* calculates largest prime factor */
int lprime(int n) {
int max = -1;
while (n % 2 == 0) {
max = 2;
n /= 2;
}
for (int i = 3; i*i <= n; i += 2) {
while (n % i == 0) {
max = i;
n = n / i;
}
}
if (n > 2) {
max = n;
}
return max;
}
/* check unusual number */
int unus(int n) {
/* find largest prime of number */
int factor = lprime(n);
/* Check if largest prime > sqrt(n) */
if ((factor*factor) > n) {
return 1; /* true */
}
else {
return 0; /* false */
}
}
/* delete digit from number */
int del(int num, int n) {
int d = log10(num)+1; /* checks amount of digits */
int revnew = 0;
int new = 0;
for (int i = 0; num != 0; i++) {
int dig = num % 10;
num = num / 10;
if(i == (d - n)) {
continue;
} else {
revnew = (revnew * 10) + dig;
}
}
for (int i = 0; revnew != 0; i++) {
new = (new*10) + (revnew % 10);
revnew = revnew / 10;
}
return new;
}
/* driver code */
int main(int argc, char* v[]) {
int m=22, n;
int x = 0;
int i = 1;
int counter = 0;
scanf("%d", &n);
int d = log10(m)+1;
while (counter < n) {
if (unus(m++)) {
counter++;
}
}
for(unus(m); i < d; i++) {
int nmin = del(m, i);
if (unus(nmin)) {
continue;
} else {
printf("%d is not supurunusual\n", (m-1));
x++;
}
}
if(x==0) {
printf("%d is superunusual!\n", (m-1));
}
return 0;
}
I hope you can understand my code. Otherwise I will explain it better.
Also, I'm quite new to coding, so please don't be to harsh...
You have a function to determine whether a number is unusual, but you do the check whether a number is super-unusual in the body of the main routine. If you extract that code into a proper function:
int is_superunusual(int m)
{
int d = log10(m) + 1;
if (unus(m) == 0) return 0;
for(int i = 0; i < d; i++) { // see footnote
int nmin = del(m, i);
if (unus(nmin) == 0) return 0;
}
return 1;
}
then you can use Eugene's code:
while (counter < n) {
if (is_superunusual(m++)) {
counter++;
}
}
printf("The su number #%d is %d\n", n, m - 1);
Your code tested for unusual numbers, not super-unusual numbers.
Footnote: If you take del(num, n) to mean "remove the nth digit from the end", you can do away with the log10 call in del. You must check all deletions anyway, so the order doesn't really matter here.

How to factorize a number?

I've been asked to factorize a number and show it in a specific way .
e.g: 100 = 2^2*5^2
This is the C++ code I've used so far with no dice , unfortunately:
#include <stdio.h>
#include <math.h>
//IsPrime indicates whether a given number is or is not prime.
bool IsPrime(long long n)
{
int j = 3;
if (n == 2)
{
return true;
}
else if (n % 2 == 0)
{
return false;
}
else
{
for (j = 3; j <= sqrt(n); j += 2)
{
if (n%j == 0)
{
return false;
}
}
}
return true;
}
int main(void)
{
long long n_orig,n, i=3 , primecount=0;
scanf("%lld", &n_orig);
n = n_orig;
if (n == 1)
{
printf("1");
return 0;
}
if (IsPrime(n))
{
printf("%lld", n);
return 0;
}
if (n % 2 == 0)
{
while (n >= 2 && n % 2 == 0)
{
primecount++;
n = n / 2;
}
if (primecount == 1)
{
printf("2*");
}
else
{
printf("2^%lld*", primecount);
}
}
primecount = 0;
n = n_orig;
while (i <= n/2)
{
if (IsPrime(i))
{
while (n >= i && n % i == 0)
{
primecount++;
n = n / i;
}
}
n = n_orig;
if (primecount == 0)
{
i++;
continue;
}
if (primecount == 1)
{
printf("%lld*", i);
}
else
{
printf("%lld^%lld*", i, primecount);
}
primecount = 0;
i+=2;
}
printf("\b");
return 0;
}
Using this code I was able to generate a few test cases, though when I uploaded my answer to the website where the codes are presumably evaluated , out of 7 test cases (which I cannot know what they exactly are) , I pass 3 , fail 3 and exceed time limit (the one that hasn't even been declared in the question) in one case. I'd really appreciate some help , and please be noob-friendly!
Also , I don't really wanna know if my answer could be improved in some way , my top priority right now is understanding why MY own code doesn't work as intended.
P.S : Usage of iostream and arrays is not allowed.
Thanks in advance.
Try this:
#include <stdio.h>
#include <math.h>
unsigned long long PrintMultiplicity(unsigned long long n,unsigned long long factor)
{
unsigned int count = 0;
while (n%factor == 0)
{
count++;
n /= factor;
}
if (count > 0)
{
printf("%llu^%u",factor,count);
if (n > 1)
printf("*");
}
return n;
}
void PrintFactorization(unsigned long long n)
{
unsigned long long factor;
unsigned int add;
printf("%llu = ",n);
n = PrintMultiplicity(n,2);
n = PrintMultiplicity(n,3);
// Check only factors that are adjacent to multiples of 6
for (factor = 5, add = 2; factor <= sqrt(n); factor += add, add = 6-add)
n = PrintMultiplicity(n,factor);
if (n > 1)
printf("%llu^1",n);
printf("\n");
}
int main()
{
unsigned long long n;
scanf("%llu",&n);
PrintFactorization(n);
return 0;
}
You need to perform some fine optimisations. Do not invoke isPrime() method for each value, instead consider a different approach so that irrelevant values can be ignored altogether at the very beginning.
Get the list of relevant primes numbers that comes under n, using Sieve of Eratosthenes concepts.
Start from the lowest prime value from the list, divide n to get intermediate values as
n / lowest_prime_that_perfectly_divide_n.
Continue doing this by checking with next higher prime value till n becomes 1. This way you would have count of each dividing factors.
You do not need prime tests, and lists of primes or prime wheels are only needed for acceleration. A simple program listing all prime factors is
#include <stdio.h>
#include <math.h>
int main(void)
{
long long n_orig,n,k;
scanf("%lld", &n_orig);
n = n_orig;
k=2;
while(k*k<=n) {
while(0==n%k) {
n = n/k;
printf("%lld ",k);
}
k++;
}
if(n>1) printf("%lld ",n);
printf("\n");
return 0;
}
This does not generate the required output format, but that can easily added to it.

How to find the sum of Prime Numbers in C within a given range?

I'm very new to programming and I was asked to find the sum of prime numbers in a given range, using a while loop. If The input is 5, the answer should be 28 (2+3+5+7+11). I tried writing the code but it seems that the logic isn't right.
CODE
#include <stdio.h>
int main()
{
int range,test;
int sum = 2;
int n = 3;
printf("Enter the range.");
scanf("%i",range);
while (range > 0)
{
int i =2;
while(i<n)
{
test = n%i;
if (test==0)
{
goto end;
}
i++;
}
if (test != 0)
{
sum = sum + test;
range--;
}
end:
n++;
}
printf("The sum is %i",sum);
return 0;
}
It would be nice if you could point out my mistake and possibly tell me how to go about from there.
first of all, in the scanf use &range and not range
scanf("%i",&range);
Second this instruction is not correct
sum = sum + test;
it should be
sum = sum + n;
and also the
while (range > 0)
should be changed to
while (range > 1)
Because in your algorithm you have already put the first element of the range in the sum sum = 2 so the while should loop range - 1 times and not range times
That's all
OK, my C is really bad, but try something like the following code. Probably doesn't compile, but if it's a homework or something, you better figure it out yourself:
UPDATE: Made it a while loop as requested.
#include <stdio.h>
int main()
{
int range, test, counter, innerCounter, sum = 1;
int countPrimes = 1;
int [50] primesArray;
primesArray[0] = 1;
printf("Enter the range.");
scanf("%i",range);
counter = 2;
while (counter <= range) {
for (innerCounter = 1; innerCounter < countPrimes; innerCounter++) {
if (counter % primesArray[innerCounter] == 0)
continue;
primesArray[countPrimes + 1] = counter;
countPrimes ++;
sum += counter;
}
counter ++
}
printf("The sum is %i",sum);
return 0;
}
I haven't done C in a while, but I'd make a few functions to simplify your logic:
#include <stdio.h>
#include <math.h>
int is_prime(n) {
int i;
for (i = 2; i <= sqrt(n); i++) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
int main() {
int range, i, sum, num_primes = 0;
printf("Enter the range: ");
scanf("%d", &range);
for (i = 2; num_primes < range; i++) {
if (is_prime(i)) {
sum += i;
num_primes++;
}
}
printf("The sum is %d", sum);
return 0;
}
Using goto and shoving all of your code into main() will make your program hard to debug.
Copy - pasted from here.
#include <stdio.h>
int main() {
int i, n, count = 0, value = 2, flag = 1, total = 0;
/* get the input value n from the user */
printf("Enter the value for n:");
scanf("%d", &n);
/* calculate the sum of first n prime nos */
while (count < n) {
for (i = 2; i <= value - 1; i++) {
if (value % i == 0) {
flag = 0;
break;
}
}
if (flag) {
total = total + value;
count++;
}
value++;
flag = 1;
}
/* print the sum of first n prime numbers */
printf("Sum of first %d prime numbers is %d\n", n, total);
return 0;
}
Output:
Enter the value for n:5
Sum of first 5 prime numbers is 28
Try the simplest approach over here. Check C program to find sum of all prime between 1 and n numbers.
CODE
#include <stdio.h>
int main()
{
int i, j, n, isPrime, sum=0;
/*
* Reads a number from user
*/
printf("Find sum of all prime between 1 to : ");
scanf("%d", &n);
/*
* Finds all prime numbers between 1 to n
*/
for(i=2; i<=n; i++)
{
/*
* Checks if the current number i is Prime or not
*/
isPrime = 1;
for(j=2; j<=i/2 ;j++)
{
if(i%j==0)
{
isPrime = 0;
break;
}
}
/*
* If i is Prime then add to sum
*/
if(isPrime==1)
{
sum += i;
}
}
printf("Sum of all prime numbers between 1 to %d = %d", n, sum);
return 0;
}

Project Euler Problem 4

I've created a solution to problem 4 on Project Euler.
However, what I find is that placing the print statement (that prints the answer) in different locations prints different answers. And for some reason, the highest value of result is 580085. Shouldn't it be 906609? Is there something wrong with my isPalindrome() method?
#include <stdio.h>
#include <stdbool.h>
int isPalindrome(int n);
//Find the largest palindrome made from the product of two 3-digit numbers.
int main(void)
{
int i = 0;
int j = 0;
int result = 0;
int palindrome = 0;
int max = 0;
//Each iteration of i will be multiplied from j:10-99
for(i = 100; i <= 999; i++)
{
for(j = 100; j <= 999; j++)
{
result = i * j;
if(isPalindrome(result) == 0)
{
//printf("Largest Palindrome: %d\n", max); //906609
//printf("Result: %d\n", result); //580085
if(result > max)
{
max = result;
//printf("Largest Palindrome: %d\n", max); //927340
}
printf("Largest Palindrome: %d\n", max); //906609
}
}
}
//printf("Largest Palindrome: %d\n", max); //998001
system("PAUSE");
return 0;
} //End of main
//Determines if number is a palindrome
int isPalindrome(int num)
{
int n = num;
int i = 0;
int j = 0;
int k = 0;
int count = 0;
int yes = 0;
//Determines the size of numArray
while(n/10 != 0)
{
n%10;
count++;
n = n/10;
}
int numArray[count];
//Fill numArray with each digit of num
for(i = 0; i <= count; i++)
{
numArray[i] = num%10;
//printf("%d\n", numArray[i]);
num = num/10;
}
//Determines if num is a Palindrome
while(numArray[k] == numArray[count])
{
k = k + 1;
count = count - 1;
yes++;
}
if(yes >= 3)
{
return 0;
}
}//End of Function
I remember doing that problem a while ago and I simply made a is_palindrome() function and brute-forced it. I started testing from 999*999 downwards.
My approach to detect a palindrome was rather different from yours. I would convert the given number to a string and compare the first char with the nth char, second with n-1 and so on.
It was quite simple (and might be inefficient too) but the answer would come up "instantly".
There is no problem in the code in finding the number.
According to your code fragment:
.
.
}
printf("Largest Palindrome: %d\n", max); //906609
}
}
}
//printf("Largest Palindrome: %d\n", max); //998001
system("PAUSE");
.
.
.
you get the result as soon as a palindrome number is found multiplying the number downwards.
You should store the palindrome in a variable max and let the code run further as there is a possibility of finding a greater palindrome further.
Note that for i=800,j=500, then i*j will be greater when compare with i=999,j=100.
Just understand the logic here.
A few issues in the isPalindrome function :
the first while loop doesn't count the number of digits in the number, but counts one less.
as a result, the numArray array is too small (assuming that your compiler supports creating the array like that to begin with)
the for loop is writing a value past the end of the array, at best overwriting some other (possibly important) memory location.
the second while loop has no properly defined end condition - it can happily compare values past the bounds of the array.
due to that, the value in yes is potentially incorrect, and so the result of the function is too.
you return nothing if the function does not detect a palindrome.
//Determines if number is a palindrome
bool isPalindrome(int num) // Change this to bool
{
int n = num;
int i = 0;
int j = 0;
int k = 0;
int count = 1; // Start counting at 1, to account for 1 digit numbers
int yes = 0;
//Determines the size of numArray
while(n/10 != 0)
{
// n%10; <-- What was that all about!
count++;
n = n/10;
}
int numArray[count];
//Fill numArray with each digit of num
for(i = 0; i < count; i++) // This will crash if you use index=count; Array indices go from 0 to Size-1
{
numArray[i] = num%10;
//printf("%d\n", numArray[i]);
num = num/10;
}
//Determines if num is a Palindrome
/*
while(numArray[k] == numArray[count-1]) // Again count-1 not count; This is really bad though what if you have 111111 or some number longer than 6. It might also go out of bounds
{
k = k + 1;
count = count - 1;
yes++;
}
*/
for(k = 1; k <= count; k++)
{
if(numArray[k-1] != numArray[count-k])
return false;
}
return true;
}//End of Function
That's all I could find.
You also need to change this
if(isPalindrome(result) == 0)
To
if(isPalindrome(result))
The Code's Output after making the modifications: Link
The correct printf is the one after the for,after you iterate through all possible values
You are using int to store the value of the palidrome but your result is bigger then 65536,
you should use unsigned
result = i * j;
this pice of code is wrong :
while(n/10 != 0) {
n%10;
count++;
n = n/10;
}
it should be:
while(n != 0) {
count++;
n = n/10;
}
As well as the changes that P.R sugested.
You could do something like this to find out if the number is palindrome:
int isPalindrom(unsigned nr) {
int i, len;
char str[10];
//convert number to string
sprintf(str, "%d", nr);
len = strlen(str);
//compare first half of the digits with the second half
// stop if you find two digits which are not equal
for(i = 0; i < len / 2 && str[i] == str[len - i - 1]; i++);
return i == len / 2;
}
I converted the number to String so I'd be able to go over the number as a char array:
private static boolean isPalindrom(long num) {
String numAsStr = String.valueOf(num);
char[] charArray = numAsStr.toCharArray();
int length = charArray.length;
for (int i = 0 ; i < length/2 ; ++i) {
if (charArray[i] != charArray[length - 1 - i]) return false;
}
return true;
}
I got correct answer for the problem, but I want to know is my coding style is good or bad from my solution. I need to know how can I improve my coding,if it is bad and more generic way.
#include<stdio.h>
#define MAX 999
#define START 100
int main()
{
int i,j,current,n,prev = 0;
for(i = START;i<=MAX;i++)
{
for(j=START;j<=MAX;j++)
{
current = j * i;
if(current > prev) /*check the current value so that if it is less need not go further*/
{
n = palindrome(current);
if (n == 1)
{
printf("The palindrome number is : %d\n",current);
prev = current; // previous value is updated if this the best possible value.
}
}
}
}
}
int palindrome(int num)
{
int a[6],temp;
temp = num;
/*We need a array to store each element*/
a[5] = temp % 10;
a[4] = (temp/10) %10;
a[3] = (temp/100) %10;
a[2] = (temp/1000) %10;
a[1] = (temp/10000) %10;
if(temp/100000 == 0)
{
a[0] = 0;
if(a[1] == a[5] && a[2] == a[4])
return 1;
}
else
{
a[0] = (temp/100000) %10;
if(a[0] == a[5] && a[1] == a[4] && a[2] == a[3])
return 1;
else
return 0;
}
}
No, the largest should be: 906609.
Here is my program:
def reverse_function(x):
return x[::-1]
def palindrome():
largest_num = max(i * x
for i in range(100, 1000)
for x in range(100, 1000)
if str(i * x) == reverse_function(str(i * x)))
return str(largest_num)
print(palindrome())

Resources