Memory overflow in C - c

#include <stdlib.h>
#include <stdio.h>
int main (){
int n, cont, fib, na = 0, nb = 1, sum_even = 0;
printf ("Insert a number and I'll tell you the respective Fibonacci: ");
scanf ("%d", &n);
for (cont = 1; cont < n; cont++) {
na += nb;
nb = na - nb;
fib = na + nb;
if (fib % 2 == 0) {
sum_even += fib;
}
}
printf ("%d\n", sum_even);
return 0;
}
I was trying to do the Project Euler Problem 2, and then I came up with this code. The problem is: I can't find the sum of the pair numbers on fibonacci's sequence for numbers over 400 or something near that, because memory overflows. In consequence, I cant solve the exercise, since it asks to find the sum of the pair numbers below 4000000 in fibonacci's sequence. Can anyone help me?
Edit:
I tried to used float type numbers to increase the answer's capacity, it seems to work till a thousand or so, but if I try with bigger numbers, I get a -nan error in bash after like 15 secs of processing (I don't really know what it means).
#include <stdlib.h>
#include <stdio.h>
int main () {
int n, cont, div;
float sum_even = 0, na = 0, nb = 1, fib;
printf ("Insert a number and I'll tell you the respective Fibonacci: ");
scanf ("%d", &n);
for (cont = 1; cont <= n; cont++) {
na += nb;
nb = na - nb;
fib = na + nb;
div = fib / 2;
if (div % 2 == 0) {
sum_even += fib;
}
}
printf ("%f\n", sum_even);
return 0;
}

What you observe is not a memory overflow, it is a numeric overflow. The whole point of the exercise was to show that overflow does happen, and make you learn techniques to deal with it. In this particular case, they expect you to either implement arbitrary precision integer arithmetic, or borrow a pre-made implementation and use it with your solution.

You misunderstood the problem statement. The task is to find the sum of
{ fib(n) : fib(n) <= 4000000 && fib(n) % 2 == 0 }
and not
{ fib(n) : n <= 4000000 && fib(n) % 2 == 0 }
That task is solved without problems with a minor modification to your code. Instead of
for (cont = 1; cont < n; cont++) {
use
while(fib <= n) {

Related

Armstrong number program in C returns wrong value

I am writing a program to see if a user entered number is Armstrong or not, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int x = 0;
printf("Enter a natural number: ");
scanf("%d", &x);
int ans = x;
// Digit Counter
int counter = 0; //Variable for number of digits in the user entered number
int b = x; //For each time number can be divided by 10 and isnt 0
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
++counter;
//Digit Counter
int sum = 0;
// Digit Finder
int D;
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
if (sum == ans){
printf("%d is a Armstrong number! :)", ans);
}else
printf("%d is not an Armstrong number :(", ans);
//Digit Finder
return 0;
}
My problem is that the program works fine apart from one point, when the program is given a Armstrong number which does not start with 1 then it behaves normally and indicates if it is an Armstrong number or not, but when i input a Armstrong number which start with 1 then it will print out the Armstrong number but -1.
For example: If i input something such as 371 which is an Armstrong number it will show that it is an Armstrong number. However if i input 1634 it will output 1633 which is 1 less than 1634.
How can i fix this problem?, also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
How can I fix this problem.
You know the number of iterations you want to make once you have calculated the digit count. So instead of looping till you reach the value of x:
for (int j = 1; j <= x; j++){
use the digit counter instead:
for (int j = 1; j <= counter; j++) {
also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
There's a number of things you can do to improve your code.
First and foremost, any piece of code should be properly indented and formatted. Right now your code has no indenting, which makes it more difficult to read and it just looks ugly in general. So, always indent your code properly. Use an IDE or a good text editor, it will help you.
Be consistent in your code style. If you are writing
if (some_cond) {
...
}
else
//do this
It is not consistent. Wrap the else in braces as well.
Always check the return value of a function you use, especially for scanf. It will save you from many bugs in the future.
if (scanf("%d", &x) == 1)
//...all OK...
else
// ...EOF or conversion failure...
exit(EXIT_FAILURE);
Your first for loop will iterate x times uselessly. You can stop when you know that you have hit 0:
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b == 0){
break;
}
counter += 1;
}
C has ++ operator. Use that instead of doing counter += 1
int D; you create this, but don't initialize it. Always initialize your variables as soon as possible
C has const qualifier keyword, which makes a value immutable. This makes your code more readable, as the reader can immediately tell that this value will not change. In your code, you can change ans variable and make it a const int because it never changes:
const int ans = x;
Use more descriptive names for your variables. ans, D don't tell me anything. Use proper names, so that the reader of your code can easily understand your code.
These are some of the things that in my opinion you should do and keep doing to improve your code and coding skills. I am sure there can be more things though. Keep your code readable and as simple as possible.
The condition in this loop
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
does not make sense because there will be numerous redundant iterations of the loop.
For example if x is equal to 153 that is contains only 3 digits the loop will iterate exactly 153 times.
Also additional increment of the variable counter after the loop
++counter;
makes the code logically inconsistent.
Instead of the loop you could write at least the following way
int counter = 0;
int b = x;
do
{
++counter;
} while ( b /= 10 );
This loop iterates exactly the number of times equal to the number of digits in a given number.
In this loop
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
it seems you did not take into account that the variable x is decreased inside the body of the loop
x /= 10; // Divides user entered number by 10 to get rid of digit found
So the loop can interrupt its iterations too early. In any case the condition of the loop again does not make great sense the same way as the condition of the first loop and only adds a bug.
The type of used variables that store a given number should be unsigned integer type. Otherwise the user can enter a negative number.
You could write a separate function that checks whether a given number is an Armstrong number.
Here you are.
#include <stdio.h>
int is_armstrong( unsigned int x )
{
const unsigned int Base = 10;
size_t n = 0;
unsigned int tmp = x;
do
{
++n;
} while ( tmp /= Base );
unsigned int sum = 0;
tmp = x;
do
{
unsigned int digit = tmp % Base;
unsigned int power = digit;
for ( size_t i = 1; i < n; i++ ) power *= digit;
sum += power;
} while ( ( tmp /= Base ) != 0 && !( x < sum ) );
return tmp == 0 && x == sum;
}
int main(void)
{
unsigned int a[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407,
1634, 8208, 9474, 54748, 92727, 93084, 548834
};
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%u is %san Armstrong number.\n", a[i], is_armstrong( a[i] ) ? "": "not " );
}
return 0;
}
The program output is
0 is an Armstrong number.
1 is an Armstrong number.
2 is an Armstrong number.
3 is an Armstrong number.
4 is an Armstrong number.
5 is an Armstrong number.
6 is an Armstrong number.
7 is an Armstrong number.
8 is an Armstrong number.
9 is an Armstrong number.
153 is an Armstrong number.
370 is an Armstrong number.
371 is an Armstrong number.
407 is an Armstrong number.
1634 is an Armstrong number.
8208 is an Armstrong number.
9474 is an Armstrong number.
54748 is an Armstrong number.
92727 is an Armstrong number.
93084 is an Armstrong number.
548834 is an Armstrong number.
Please remove j++ from 2nd loop for (int j = 1; j <= x; j++)
I tried this:
void armstrong(int x)
{
// count digits
int counter = 0, temp = x, sum = 0;
while(temp != 0)
{
temp = temp/10;
++counter; // Note: pre increment faster
}
// printf("count %d\n",counter);
temp = x;
while(temp != 0)
{
sum += pow(temp % 10, counter);
temp = temp/10;
}
// printf("sum %d\n",sum);
if(x == sum)
{
printf("Armstrong\n");
}
else
{
printf("No Armstrong\n");
}
}
int main(){
armstrong(371);
armstrong(1634);
return 0;
}
Let's take this and add the ability to handle multiple numeric bases while we're at it. Why? BECAUSE WE CAN!!!! :-)
#include <stdio.h>
#include <math.h>
double log_base(int b, double n)
{
return log(n) / log((double)b);
}
int is_armstrong_number(int b, /* base */
int n)
{
int num_digits = trunc(log_base(b, (double)n)) + 1;
int sum = 0;
int remainder = n;
while(remainder > 0)
{
sum = sum + pow(remainder % b, num_digits);
remainder = (int) (remainder / b);
}
return sum == n;
}
int main()
{
printf("All the following are valid Armstrong numbers\n");
printf(" 407 base 10 - result = %d\n", is_armstrong_number(10, 407));
printf(" 0xEA1 base 16 - result = %d\n", is_armstrong_number(16, 0xEA1));
printf(" 371 base 10 - result = %d\n", is_armstrong_number(10, 371));
printf(" 1634 base 10 - result = %d\n", is_armstrong_number(10, 1634));
printf(" 0463 base 8 - result = %d\n", is_armstrong_number(8, 0463));
printf("All the following are NOT valid Armstrong numbers\n");
printf(" 123 base 10 - result = %d\n", is_armstrong_number(10, 123));
printf(" 0x2446 base 16 - result = %d\n", is_armstrong_number(16, 0x2446));
printf(" 022222 base 8 - result = %d\n", is_armstrong_number(8, 022222));
}
At the start of is_armstrong_number we compute the number of digits directly instead of looping through the number. We then loop through the digits of n in base b, summing up the value of the digit raised to the number of digits in the number, for the given numeric base. Once the remainder hits zero we know there are no more digits to compute and we return a flag indicating if the given number is an Armstrong number in the given base.

C programming segmentation error

This is the code for finding the last digit of nth Fibonacci number
#include <stdio.h>
int main() {
long i, j, fib[1000];
fib[0] = 0;
fib[1] = 1;
scanf("%li", &j);
for(i = 2; i != 1000; i++)
{
fib[i] = (fib[i - 2] + fib[i - 1]) % 10;
}
printf("%li", fib[j]);
return 0;
}
It shows segmentation fault. How can I fix it?
The only reason I can see for this not working is that you're inputting a number that is outside of the range 0 <= j <= 999. This is due to the limit on your array variable: long fib[1000].
This can be fixed in one of two ways, depending on what you want:
You can add a check to make sure that the input value j is in range, and ask for another number if it isn't.
You can stop using an array variable, and only use three variables: one to store the current value, and two more to store the two previous values. These are updated as you calculate. A loop is still used with this approach.
#1 is the simplest to implement, as shown here:
while (1)
{
printf("j > ");
scanf(" %li", &j);
if (0 <= j <= 999)
{
break;
}
}
#2 is a bit more complex, but it effectively removes the arbitrary limit that j must be less than 1000 (and changes the limit so that j must be less than LONG_MAX):
// num_cache[0] is the number before the previous number
// num_cache[1] is the previous number to the current number
long num_cache[2] = { 0, 0 };
long current_fib = 1;
for (i = 2; i < j; i++)
{
// Push back the numbers
num_cache[0] = num_cache[1];
num_cache[1] = current_fib;
// Calculate the new number
current_fib = (num_cache[0] + num_cache[1]) % 10;
}
One of those solutions should fix your issue.
It appears that the segmentation fault is occurring due to inadequate checking of input values.
If the input to the program is not a valid number, then the value of j will be unchanged after the call to scanf(). Since this variable is uninitialized, this will result in undefined behaviour when you attempt to access the jth element of the fib[] array.
If the value of j is less than zero or greater than 999, you will be accessing a non-existent member of fib[] when you exit the for() loop. Your code should check that j is valid before continuing.
Here's your code with a few modifications to implement these safeguards and move the "magic number" 1000 to a #defined value.
#include <stdio.h>
#define FIBONACCI_LIMIT 1000L
int main(){
long i, j, fib[FIBONACCI_LIMIT];
fib[0] = 0;
fib[1] = 1;
if (scanf("%li", &j) != 1)
{
fprintf(stderr, "Invalid input\n");
return 1;
}
if (j<0 || j>=FIBONACCI_LIMIT)
{
fprintf(stderr, "Number must be in range 0 <= n < %li\n", FIBONACCI_LIMIT);
return 2;
}
for(i=2; i!=1000; i++)
{
fib[i] = (fib[i-2] + fib[i-1])%10;
}
printf("%li\n", fib[j]);
return 0;
}
The code can be improved by getting rid of the fib[] array altogether, since there is no need to store 1000 values when you only need to calculate one value. Furthermore, the final digits of numbers in the Fibonacci sequence form a repeating pattern of 60 values, so your first step should be to replace j with j % 60. Here is an improved version of the code that will work with any non-negative input capable of fitting into a long integer:
#include <stdio.h>
int main() {
long i, j, t, f0=0, f1=1;
if (scanf("%li", &j) != 1)
{
fprintf(stderr, "Invalid input\n");
return 1;
}
if (j < 0)
{
fprintf(stderr, "Number must be non-negative\n");
return 2;
}
j %= 60;
for (i=0; i<j; i++)
{
t = f0;
f0 = f1;
f1 = (f1 + t) % 10;
}
printf("%li\n", f0);
return 0;
}
You did not show what value of the variable j was entered.
Take into account that the next Fibonacci number is calculated incorrectly in the loop.
If to use the integer type unsigned long long then an object of this type can accommodate only 93 Fibonacci numbers.
The program can look like
#include <stdio.h>
#define N 100
int main(void)
{
while ( 1 )
{
unsigned long long fib[N] = { 0, 1 };
unsigned int n;
printf( "Enter a sequantial number of a fibonacci number (0 - exit): " );
if ( scanf("%u", &n) != 1 || n == 0 ) break;
unsigned int i = 2;
for (; i < N && i <= n && fib[i-1] <= fib[i-2] + fib[i-1]; i++)
{
fib[i] = fib[i - 2] + fib[i - 1];
}
if (n < i)
{
printf("#%u: %llu %llu\n", n, fib[n], fib[n] % 10);
}
else
{
puts("Too big fibonacci number");
}
}
return 0;
}
Its output might look like
Enter a sequantial number of a fibonacci number (0 - exit): 1
#1: 1 1
Enter a sequantial number of a fibonacci number (0 - exit): 2
#2: 1 1
Enter a sequantial number of a fibonacci number (0 - exit): 3
#3: 2 2
Enter a sequantial number of a fibonacci number (0 - exit): 93
#93: 12200160415121876738 8
Enter a sequantial number of a fibonacci number (0 - exit): 94
Too big fibonacci number
Enter a sequantial number of a fibonacci number (0 - exit): 0

Combination formula "n! / ((n-k)!*k!)" doesn't work [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
why is = n! / ((n-k)!*k!) not printing?
Also will this code solve the problem below?
stuck.
"The number of combinations of n things taken k at a time as an integer"
A little more clarification: "For example, the combinations of four items a,b,c,d taken three at a time are abc, abd, acd, and bcd. In other words, there are a total of four different combinations of four things "taken three at a time"."
#include <stdio.h>
#include <math.h>
int main (void)
{
int z = 0, n_in, k_in, k = 0, n = 0, result, nfr = 0, kfr = 0;
do
{
printf("Enter the number of items in the list (n):");
scanf("%d*c", &n_in);
if (n_in>1 && n_in<11)
{
printf("Enter the number of items to choose (k)");
scanf("%d*c", &k_in);
if (k_in>0 && k_in<5)
{
if (k_in <= n_in)
{
k_in = k;
n_in = n;
result = n! / ((n-k)!*k!);
z = 1;
}
else
printf("?Please Try again k must be less than n \n");
}
else
printf("?Invalid input: Number must be between 1 and 4 \n");
}
else
printf("?Invalid input: Number must be between 1 and 10 \n");
} while (z == 0);
result = (nfr / (nfr * kfr));
printf("k value = %d n value = %d the result is %d", nfr, kfr, result);
return 0;
}
This line:
result = n! / ((n-k)!*k!);
...is not valid C code. ! in C means "not".
You will need to provide a factorial function so that you can call:
result = factorial(n) / (factorial(n-k) * factorial(k));
! is not the NOT operator in C. Use this factorial function instead.
int factorial(int n)
{
return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
}
So your calculation would be:
result = factorial(n) / (factorial(n-k)*factorial(k));
There are probably faster ways to do it, but this is readable.
Also, this line
result = (nfr / (nfr * kfr));
Does not make any sense to me, since both nfr and kfr are zero, but I guess you wanted to get the code to compile, before completing the logic.
EDIT:
complete code should look like this:
#include <stdio.h>
#include <math.h>
int factorial(int n)
{
return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
}
int main (void)
{
int z = 0, n_in, k_in, k = 0, n = 0, result, nfr = 0, kfr = 0;
do
{
printf("Enter the number of items in the list (n):");
scanf("%d*c", &n_in);
if (n_in>1 && n_in<11)
{
printf("Enter the number of items to choose (k)");
scanf("%d*c", &k_in);
if (k_in>0 && k_in<5)
{
if (k_in <= n_in)
{
k_in = k;
n_in = n;
result = factorial(n) / (factorial(n-k)*factorial(k));
//result = n! / ((n-k)!*k!);
z = 1;
}
else
printf("?Please Try again k must be less than n \n");
}
else
printf("?Invalid input: Number must be between 1 and 4 \n");
}
else
printf("?Invalid input: Number must be between 1 and 10 \n");
} while (z == 0);
//result = (nfr / (nfr * kfr));
printf("k value = %d n value = %d the result is %d\n", nfr, kfr, result);
return 0;
}
Output:
~/so$ gcc test.cc
~/so$ ./a.out
Enter the number of items in the list (n):3
Enter the number of items to choose (k)2
k value = 0 n value = 0 the result is 1
~/so$

Extracting individual digits from a long in C

I'm doing a homework assignment for my course in C (first programming course).
Part of the assignment is to write code so that a user inputs a number up to 9 digits long, and the program needs to determine whether this number is "increasing"/"truly increasing"/"decreasing"/"truly decreasing"/"increasing and decreasing"/"truly decreasing and truly increasing"/"not decreasing and not increasing". (7 options in total)
Since this is our first assignment we're not allowed to use anything besides what was taught in class:
do-while, for, while loops, else-if, if,
break,continue
scanf, printf ,modulo, and the basic operators
(We can't use any library besides for stdio.h)
That's it. I can't use arrays or getchar or any of that stuff. The only function I can use to receive input from the user is scanf.
So far I've already written the algorithm with a flowchart and everything, but I need to separate the user's input into it's distinct digits.
For example, if the user inputs "1234..." i want to save 1 in a, 2 in b, and so on, and then make comparisons between all the digits to determine for example whether they are all equal (increasing and decreasing) or whether a > b >c ... (decreasing) and so on.
I know how to separate each digit by using the % and / operator, but I can't figure out how to "save" these values in a variable that I can later use for the comparisons.
This is what I have so far:
printf("Enter a positive number : ");
do {
scanf ("%ld", &number);
if (number < 0) {
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
while (number < 0) {
a = number % 10;
number = number - a;
number = number / 10;
b = a;
}
Why not scan them as characters (string)? Then you can access them via an array offset, by subtracting the offset of 48 from the ASCII character code. You can verify that the character is a digit using isdigit from ctype.h.
EDIT
Because of the incredibly absent-minded limitations that your professor put in place:
#include <stdio.h>
int main()
{
int number;
printf("Enter a positive number: ");
do
{
scanf ("%ld", &number);
if (number < 0)
{
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
int a = -1;
int b = -1;
int c = -1;
int d = -1;
int e = -1;
int f = -1;
int g = -1;
int h = -1;
int i = -1;
while (number > 0)
{
if (a < 0) a = number % 10;
else if (b < 0) b = number % 10;
else if (c < 0) c = number % 10;
else if (d < 0) d = number % 10;
else if (e < 0) e = number % 10;
else if (f < 0) f = number % 10;
else if (g < 0) g = number % 10;
else if (h < 0) h = number % 10;
else if (i < 0) i = number % 10;
number /= 10;
}
/* Printing for verification. */
printf("%i", a);
printf("%i", b);
printf("%i", c);
printf("%i", d);
printf("%i", e);
printf("%i", f);
printf("%i", g);
printf("%i", h);
printf("%i", i);
return 0;
}
The valid numbers at the end will be positive, so those are the ones you validate to meet your different conditions.
Since you only need to compare consecutive digits, there is an elegant way to do this without arrays:
int decreasing = 2;
int increasing = 2;
while(number > 9)
{
int a = number % 10;
int b = (number / 10) % 10;
if(a == b)
{
decreasing = min(1, decreasing);
increasing = min(1, increasing);
}
else if(a > b)
decreasing = 0;
else if(a < b)
increasing = 0;
number /= 10;
}
Here, we walk through the number (by dividing by 10) until only one digit remains. We store info about the number up to this point in decreasing and increasing - a 2 means truly increasing/decreasing, a 1 means increasing/decreasing, and a 0 means not increasing/decreasing.
At each step, a is the ones digit and b is the tens. Then, we change increasing and decreasing based on a comparison between a and b.
At the end, it should be easy to turn the values of increasing and decreasing into the final answer you want.
Note: The function min returns the smaller of its 2 arguments. You should be able to write your own, or replace those lines with if statements or conditionals.
It's stupid to ask you to do loops without arrays --- but that's your teacher's fault, not yours.
That being said, I would do something like this:
char c;
while (1) {
scanf("%c", &c);
if (c == '\n') /* encountered newline (end of input) */
break;
if (c < '0' || c > '9')
break; /* do something to handle bad characters? */
c -= '0';
/*
* At this point you've got 0 <= c < 9. This is
* where you do your homework :)
*/
}
The trick here is that when you type numbers into a program, you send the buffer all at once, not one character at a time. That means the first scanf will block until the entire string (i.e. "123823" or whatever) arrives all at once, along with the newline character ( '\n' ). Then this loop parses that string at its leisure.
Edit For testing the increasing/decreasing-ness of the digits, you may think you need to store the entire string, but that's not true. Just define some additional variables to remember the important information, such as:
int largest_digit_ive_seen, smallest_digit_ive_seen, strict_increasing_thus_far;
etc. etc.
Let us suppose you have this number 23654
23654 % 10000 = 2 and 3654
3654 % 1000 = 3 and 654
654 % 100 = 6 and 54
54 % 10 = 5 and 4
4
This way you can get all the digits. Of course, you have to know if the number is greater than 10000, 1000, 100 or 10, in order to know the first divisor.
Play with sizeof to get the size of the integer, in order to avoid a huge if...else statement
EDIT:
Let us see
if (number>0) {
// Well, whe have the first and only digit
} else if (number>10) {
int first_digit = number/10;
int second_digit = number % 10;
} else if (number>100) {
int first_digit = number/100;
int second_digit = (number % 100)/10;
int third_digit = (number % 100) % 10;
} ...
and so on, I suppose
// u_i is the user input, My homework asked me to extract a long long, however, this should also be effective for a long.
int digits = 0;
long long d_base = 1;
int d_arr[20];
while (u_i / d_base > 0)
{
d_arr[digits] = (u_i - u_i / (d_base * 10) * (d_base * 10)) / d_base;
u_i -= d_arr[digits] * d_base;
d_base *= 10;
digits++;
}
EDIT: the extracted individual digit now lives in the int array d_arr. I'm not good at C, so I think the array declaration can be optimized.
Here's a working example in plain C :
#include <stdio.h>
unsigned long alePow (unsigned long int x, unsigned long int y);
int main( int argc, const char* argv[] )
{
int enter_num, temp_num, sum = 0;
int divisor, digit, count = 0;
printf("Please enter number\n");
scanf("%d", &enter_num);
temp_num = enter_num;
// Counting the number of digits in the entered integer
while (temp_num != 0)
{
temp_num = temp_num/10;
count++;
}
temp_num = enter_num;
// Extracting the digits
printf("Individual digits in the entered number are ");
do
{
divisor = (int)(alePow(10.0, --count));
digit = temp_num / divisor;
temp_num = temp_num % divisor;
printf(" %d",digit);
sum = sum + digit;
}
while(count != 0);
printf("\nSum of the digits is = %d\n",sum);
return 0;
}
unsigned long alePow(unsigned long int x, unsigned long int y) {
if (x==0) { return 0; }
if (y==0||x==1) { return 1; }
if (y==1) { return x; }
return alePow(x*x, y/2) * ((y%2==0) ? 1 : x);
}
I would suggest loop-unrolling.
int a=-1, b=-1, c=-1, d=-1, e=1, f=-1, g=-1, h=-1, i=-1; // for holding 9 digits
int count = 0; //for number of digits in the given number
if(number>0) {
i=number%10;
number/=10;
count++;
}
if(number>0) {
h=number%10;
number/=10;
count++;
}
if(number>0) {
g=number%10;
number/=10;
count++;
}
....
....
/* All the way down to the storing variable a */
Now, you know the number of digits (variable count) and they are stored in which of the variables. Now you have all digits and you can check their "decreasing", "increasing" etc with lots of if's !
I can't really think of a better soltion given all your conditions.

Finding largest prime factor of a composite number in c

I am accepting a composite number as an input. I want to print all its factors and also the largest prime factor of that number. I have written the following code. It is working perfectly ok till the number 51. But if any number greater than 51 is inputted, wrong output is shown. how can I correct my code?
#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++)
{
if(i%j > 0)
{
b = i;
}
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);
}
This is a bit of a spoiler, so if you want to solve this yourself, don't read this yet :). I'll try to provide hints in order of succession, so you can read each hint in order, and if you need more hints, move to the next hint, etc.
Hint #1:
If divisor is a divisor of n, then n / divisor is also a divisor of n. For example, 100 / 2 = 50 with remainder 0, so 2 is a divisor of 100. But this also means that 50 is a divisor of 100.
Hint #2
Given Hint #1, what this means is that we can loop from i = 2 to i*i <= n when checking for prime factors. For example, if we are checking the number 100, then we only have to loop to 10 (10*10 is <= 100) because by using hint #1, we will get all the factors. That is:
100 / 2 = 50, so 2 and 50 are factors
100 / 5 = 20, so 5 and 20 are factors
100 / 10 = 10, so 10 is a factor
Hint #3
Since we only care about prime factors for n, it's sufficient to just find the first factor of n, call it divisor, and then we can recursively find the other factors for n / divisor. We can use a sieve approach and mark off the factors as we find them.
Hint #4
Sample solution in C:
bool factors[100000];
void getprimefactors(int n) {
// 0 and 1 are not prime
if (n == 0 || n == 1) return;
// find smallest number >= 2 that is a divisor of n (it will be a prime number)
int divisor = 0;
for(int i = 2; i*i <= n; ++i) {
if (n % i == 0) {
divisor = i;
break;
}
}
if (divisor == 0) {
// we didn't find a divisor, so n is prime
factors[n] = true;
return;
}
// we found a divisor
factors[divisor] = true;
getprimefactors(n / divisor);
}
int main() {
memset(factors,false,sizeof factors);
int f = 1234;
getprimefactors(f);
int largest;
printf("prime factors for %d:\n",f);
for(int i = 2; i <= f/2; ++i) {
if (factors[i]) {
printf("%d\n",i);
largest = i;
}
}
printf("largest prime factor is %d\n",largest);
return 0;
}
Output:
---------- Capture Output ----------
> "c:\windows\system32\cmd.exe" /c c:\temp\temp.exe
prime factors for 1234:
2
617
largest prime factor is 617
> Terminated with exit code 0.
I presume you're doing this to learn, so I hope you don't mind a hint.
I'd start by stepping through your algorithm on a number that fails. Does this show you where the error is?
You need to recode so that your code finds all the prime numbers of a given number, instead of just calculating for the prime numbers 2,3, and 5. In other words, your code can only work with the number you are calculating is a prime number or is a multiple of 2, 3, or 5. But 7, 11, 13, 17, 19 are also prime numbers--so your code should simply work by finding all factors of a particular number and return the largest factor that is not further divisible.
Really, this is very slow for all but the smallest numbers (below, say, 100,000). Try finding just the prime factors of the number:
#include <cmath>
void addfactor(int n) {
printf ("%d\n", n);
}
int main()
{
int d;
int s;
int c = 1234567;
while (!(c&1)) {
addfactor(2);
c >>= 1;
}
while (c%3 == 0) {
addfactor(3);
c /= 3;
}
s = (int)sqrt(c + 0.5);
for (d = 5; d <= s;) {
while (c % d == 0) {
addfactor(d);
c /= d;
s = (int)sqrt(c + 0.5);
}
d += 2;
while (c % d == 0) {
addfactor(d);
c /= d;
s = (int)sqrt(c + 0.5);
}
d += 4;
}
if (c > 1)
addfactor(c);
return 0;
}
where addfactor is some kind of macro that adds the factor to a list of prime factors. Once you have these, you can construct a list of all the factors of the number.
This is dramatically faster than the other code snippets posted here. For a random input like 10597959011, my code would take something like 2000 bit operations plus 1000 more to re-constitute the divisors, while the others would take billions of operations. It's the difference between 'instant' and a minute in that case.
Simplification to dcp's answer(in an iterative way):
#include <stdio.h>
void factorize_and_print(unsigned long number) {
unsigned long factor;
for(factor = 2; number > 1; factor++) {
while(number % factor == 0) {
number = number / factor;
printf("%lu\n",factor);
}
}
}
/* example main */
int main(int argc,char** argv) {
if(argc >= 2) {
long number = atol(argv[1]);
factorize_and_print(number);
} else {
printf("Usage: %s <number>%<number> is unsigned long", argv[0]);
}
}
Note: There is a number parsing bug here that is not getting the number in argv correctly.

Resources