This question already has answers here:
Algorithm to find all the exact divisors of a given integer
(7 answers)
Closed 5 years ago.
The assignment was to write a program which reads in an integer k, and prints out the number of positive integers
between 1 and 100000 (inclusive) which have exactly k divisors. As an example, the number 24 has 8 divisors:
1, 2, 3, 4, 6, 8, 12, and 24.
I have a running programme, but is there anyway i could make the search faster??
#include <stdio.h>
#include <math.h>
int main(void)
{ int a; //user input//
int divisors; //running total of number of divisors//
int sum; //running total of numbers with the required number of divisors//
printf("Enter the target number of divisors:");
scanf("%d", &a);
printf("\n");
int i;
for (i=1; i<=100000; i++)
{
divisors=2;
int p;
for(p=2; p<i; p++)
{if (i%p==0)
divisors++;}
if (divisors==a)
sum++;}
printf("There are %d numbers between 1 and 100000 inclusive which have exactly %d divisors.", sum, a);
return 0;
}
Example code. Moved declarations for i and p to be compatible with old C type compilers (I'm using Microsoft / Visual Studio). Uses ceil(sqrt(i)) outer loops. The code handles an input of 1 (only the number 1 has 1 divisor). An input of 2 will output the number of prime numbers less than 100,000 (there are 9592 prime numbers less than 100,000).
This method takes a bit over 21 million iterations. Number of iterations ~= .67 n sqrt(n).
#include <stdio.h>
int main(void)
{
int a; /* user input */
int divisors; /* total number of divisors */
int sum; /* count of numbers with required number of divisors */
int i; /* moved here for C compiler */
int p; /* moved here for C compiler */
int sqrti; /* ceil(sqrt(i)) */
printf("Enter the target number of divisors: ");
scanf("%d", &a);
printf("\n");
sum = 0; /* init sum */
sqrti = 1; /* init sqrti */
for (i = 1; i <= 100000; i++)
{
divisors = 0; /* init number of divisors */
if(sqrti*sqrti < i) /* update sqrti as needed */
sqrti += 1;
for(p = 1; p < sqrti; p++)
if(i%p == 0) /* if p is a divisor, count it and i/p */
divisors += 2;
if(p*p == i) /* if p*p == i, count it */
divisors += 1;
if (divisors == a) /* if i has a divisors, increment sum */
sum += 1;
}
printf("There are %d numbers from 1 to 100000 inclusive which have exactly %d divisors.\n", sum, a);
return 0;
}
If an array can be used similar to sieve method for primes, this method takes a bit over 1 million iterations. Number of iterations ~= n ln(n).
#include <stdio.h>
#define n 100000
int main(void)
{
int * cnt = (int *)calloc(n+1, sizeof(int));
int d;
printf("Enter the target number of divisors: ");
scanf("%d", &d);
/* time complexity O(n log(n)) */
{
int i, j;
for (i = 1; i <= n; i++) {
for(j = i; j <= n; j += i) {
cnt[j]++;
}
}
}
{
int i;
int sum = 0;
for (i = 1; i <= n; i++)
sum += (cnt[i] == d) ? 1 : 0;
printf("excactly %d numbers have %d divisors\n", sum, d);
}
free(cnt);
return 0;
}
Rather than checking for the value of p uptil i we can optimize by checking until sqrt(i) and instead of incrementing divisors by 1, we increament it by 2, one for the number say k divided by i and second for the number i/k.
n=1000000;
for (i=1; i<=10000; i++)
{
divisors=2;
int p;
for(p=2; p<=sqrt(i); p++)
{
if (i%p==0)
{
if(p != (i/p)
divisors = divisors + 2;
else
divisors++;
}
}
if (divisors==a)
sum++;
}
Related
#include <stdio.h>
#include <math.h>
int main() {
int n, count, sum;
printf("Enter upper bound n \n");
scanf("%d", &n);
for (int a = 1; a <= n; a++) {
count = 0;
sum = 0;
for (int i = 2; i <= sqrt(a); ++i) {
if (a % i == 0) {
count++;
break;
}
}
if (count == 0 && a != 1) {
sum = a + sum;
}
}
printf("%d", sum);
}
The program is my attempt to print summation of primes < n. I am getting sum = 0 every time and I am unable to fix this issue.
The reason you do not get the sum of primes is you reset the value of sum to 0 at the beginning of each iteration. sum will be 0 or the value of the n if n happens to be prime.
Note also that you should not use floating point functions in integer computations: i <= sqrt(a) should be changed to i * i <= a.
The test on a != 1 can be removed if you start the loop at a = 2.
Here is a modified version:
#include <stdio.h>
int main() {
int n = 0, sum = 0;
printf("Enter upper bound n: \n");
scanf("%d", &n);
// special case 2
if (n >= 2) {
sum += 2;
}
// only test odd numbers and divisors
for (int a = 3; a <= n; a += 2) {
sum += a;
for (int i = 3; i * i <= a; i += 2) {
if (a % i == 0) {
sum -= a;
break;
}
}
}
printf("%d\n", sum);
return 0;
}
For large values of n, a much more efficient approach would use an array and perform a Sieve of Eratosthenes, a remarkable greek polymath, chief librarian of the Library of Alexandria who was the first to compute the circumference of the earth, 2300 years ago.
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int n = 0;
long long sum = 0;
if (argc > 1) {
sscanf(argv[1], "%i", &n);
} else {
printf("Enter upper bound n: \n");
scanf("%i", &n);
}
// special case 2
if (n >= 2) {
sum += 2;
}
unsigned char *p = calloc(n, 1);
for (int a = 3; a * a <= n; a += 2) {
for (int b = a * a; b < n; b += a + a) {
p[b] = 1;
}
}
for (int b = 3; b < n; b += 2) {
sum += p[b] * b;
}
free(p);
printf("%lld\n", sum);
return 0;
}
Error about sum getting set to zero inside the loop has been already pointed out in previous answers
In current form also, your code will not return zero always. It will return zero if value of upper bound is given as non prime number. If prime number is given as upper bound, it will return that number itself as sum.
As mentioned in comment you should initialize sum before first loop something like
int n, count, sum=0;
or you can initialize sum in the loop like
for(a=1,sum=0;a <= n; a++)
and remove sum=0; inside the first loop because it changes sum to 0 every time first loop executes. You can check this by inserting this lines to your code
printf("Before sum %d",sum);
sum = 0;
printf("After Sum %d",sum);
make sure sure that if you are initializing sum in the loop, define "a" in outer of the loop if not the sum goes to local variable to for loop and it hides the outer sum.
What I want to do is to get a cumulative sum of previous integers starting from 1, for example:
If my input is 4, then the function should work in this way;
1 + (1+2) + (1+2+3) + (1+2+3+4) = 20.
And the output needs to be 20. Also, I have to get this done by a function, not in main(); function while using int n as the only variable.
What I've tried is to make a function which adds from 1 to integer N, and use 'for'to make N start from 1, so that it can fully add the whole numbers until it reaches N.
#include <stdio.h>
int sum(int n);
int main() {
int n, input, sum;
sum = 0;
scanf("%d", &n);
for (n = 0; n <= input; n++) {
sum += n;
}
printf("%d", sum);
return 0;
}
int sum(int n) {
int i, n, sum = 0;
scanf("%d", &n);
for (i = 1; i <= n; i += 1){
sum += i;
}
return n;
}
What I expected when the input is 4 is 20, but the actual output is 10.
I would have written it this way, remarks are where changes been made
#include <stdio.h>
int sum(int n);
int main() {
int n, input, sum;
// sum = 0; // no need for this
scanf("%d", &n);
/* the next for has no use
for (n = 0; n <= input; n++) {
sum += n;
} */
// I would be adding some input sanitazing if possible here
printf("%d", sum(n));
return 0;
}
int sum(int n) {
int i, /*n, */ rsum = 0; // n is already a parameter, rsum for running sum
// scanf("%d", &n); // nope nope, scanf and printf should be avoided in functions
for (i = 1; i <= n; i++){ // changed i +=1 with i++ , easier to read
for (j=1;j<=i;j++) // need this other loop inside
rsum += j;
}
return rsum;
}
Here it is with a single loop; very fast.
#include <stdio.h>
int cumulative_sum(int m)
{
int sum = 0;
for(int n=1; n<=m; ++n) sum += n*(n+1);
return sum/2;
}
int main(void)
{
int n;
printf("Input value N: ");
scanf("%d", &n);
printf("Answer is %d\n", cumulative_sum(n));
return 0;
}
The main issue is in the function, you are doing only 1 loop (you have also some logical things, which compiler should tell you, like same naming of variable and function.. eg.),
so in case you will put 4 as the input, loop will do only 1+2+3+4, but your case if different, you want to make suma of all iterations like 1 + (1+2) + (1+2+3) + (1+2+3+4)
you are doing only last step basically (1+2+3+4), 4 iterations (4x suma), but actually you need 10 iterations (due suma of all particular suma of elements)
As suggested, try to debug your code - What is a debugger and how can it help me diagnose problems?
- it will really help you do understand your code
As mentioned, the issue is in
int sum(int n) {
int i, n, sum = 0;
scanf("%d", &n);
for (i = 1; i <= n; i += 1){
sum += i;
}
return n;
}
You have to make two loops eg. like follows:
int sum,n = 0;
//scanf("%d", &n);
n = 4; //input simulation
//just for demonstration
int iterations = 0;
//counter for total loops (how many "brackets" needs to be count)
for(int loopsCounter = 1; loopsCounter <= n;loopsCounter++){
//counter for child elements in brackets (like 1+2 ,1+2+3, ..)
for (int sumaLoopCounter = 1; sumaLoopCounter <= loopsCounter; sumaLoopCounter++){
//simply make sum with the given number
/* first step 0 +1
second 1+2 added to previous suma = 1+3
third 1+2+3,.. added to previous = 4+6
...
*/
sum += sumaLoopCounter;
//just testing for demonstration
iterations++; //iterations = iterations + 1
}
}
printf("%i \n",iterations);
printf("%i",sum);
Then you got output as expected - sum of all "bracket elements" and 10 iterations, which matches numbers of needed additions
10
20
I have return the code to find a factorial and to display trailing zeros at the end of the factorial, but the output is wrong... could you please help me to find the mistake?
#include <stdio.h>
int main() {
int m = 1, i, N, count = 0;
scanf("%d", &N);
for (i = 1; i <= N; i++) {
m = m * i;
}
printf("%d", m);
while (m > 0) {
if ((m % 10) == 0) {
count = count + 1;
m = m / 10;
}
break;
}
printf("%d", count);
return 0;
}
Your code only works for very small values of N: up to 9. For slightly larger values, you would need to add an else keyword before the break statement and you would get a correct result for a few more cases.
For larger values, you must compute the power of 5 that divides the factorial. You can do this incrementally by summing the power of 5 that divide each individual number up to and including N.
#include <stdio.h>
int main() {
int N, count;
if (scanf("%d", &N) != 1)
return 1;
/* only consider factors that are multiples of 5 */
count = 0;
for (int i = 5; i <= N; i += 5) {
for (int j = i; j % 5 == 0; j /= 5)
count++;
}
printf("%d\n", count);
return 0;
}
An even simpler and faster solution is this: compute the number of multiples of 5 less or equal to N, add the number of multiples of 5*5, etc.
Here is the code:
#include <stdio.h>
int main() {
int N, count;
if (scanf("%d", &N) != 1)
return 1;
count = 0;
for (int i = N; (i /= 5) > 0;) {
count += i;
}
printf("%d\n", count);
return 0;
}
you have two problems
your collapse the two outputs so you see only one of them / you cannot see who is who, just add a separator between them
an else is missing when you count so you count to only up to 1 and the result is wrong from factorial 10
So the minimal changes produce :
int main()
{
int m=1,i,N,count=0;
scanf("%d",&N);
for(i=1;i<=N;i++)
{
m=m*i;
}
printf("%d\n",m); /* <<< added \n */
while(m>0)
{
if((m%10)==0)
{
count=count+1;
m=m/10;
}
else /* <<< added else */
break;
}
printf("%d\n",count); /* <<< added \n */
return 0;
}
after the changes :
pi#raspberrypi:/tmp $ ./a.out
5
120
1
pi#raspberrypi:/tmp $ ./a.out
10
3628800
2
Of course that supposes first you are able to compute the factorial without overflow
I also encourage you to check a value was read by scanf, checking it returns 1
#include <stdio.h>
int main()
{
int n,i,f=1,t,c=0;
printf("Enter number ");
scanf("%d",&n);
t=n;
for(i=1;t>=5;i++)
{
t=n/5;
c=c+t;
n=t;
}
printf("number of zeros are %d",c);
return 0;
}
I have the following code which I'm trying to use to show how many times a certain number appears throughout the array. I want it to print out how many times it counted a specific number. (all numbers range from 0-20, with an index of 0 - 99).
void count_frequency(int *number) {
int i;
int j;
int len = sizeof number / sizeof(int);
printf("%i\n", len);
printf("reached here");
for(i = 0; i < 99; i++){ //index{
int c = 0;
for(j = 0; j < 99; j++){
if(number[j] == number[i]){
c++;
}else{
continue;
}
}
printf("%i\n", c);
//printf("%i\n", number[i]);
}
}
int main(){
int i;
int table[MAX];
int len = sizeof table / sizeof(int);
printf("%ireached before loop\n", len);
for(i = 0; i < len; i++){
table[i] = random_in_range(0, 20);
}
count_frequency(table);
//printf("%i", sizeof(table) / sizeof(int));
return 0;
}
int len = sizeof number / sizeof(int);
will not going to give you what you are expecting. number is a pointer variable not an array. Change your function to
void count_frequency(int *number, int len) {
int i;
int j;
int index[21] = {0};
printf("%i\n", len);
printf("reached here");
for(i = 0; i < len; i++){ //index{
index[number[i]%21]++;
}
for(i = 0; i < 21; i++)
printf("%d", index[i]);
}
and your function call should be
count_frequency(table, len);
Here you are. Honestly there was some magical thinking in your code. This works - it's not "the best" but an improvement on what you had. Let me know if this isn't clear. My definition of rand_in_range is not completely accurate - it will bias very slightly towards lower numbers.
include <stdio.h>
#include <stdlib.h>
#define MAX 100
#define random_in_range(a,b) ( rand() % ((b) - (a) + 1) + (a) )
void count_frequency(int *table, int *output, int n1, int n2) {
// n1 = number of elements in table
// n2 = number of elements in output
int i;
// int len = sizeof number / sizeof(int); <<<< meaningless!
// printf("%i\n", len);
// printf("reached here");
for(i = 0; i < n1; i++) { // loop over the elements in the table
output[table[i] %n 2]++; // using % n2 so we don't go outside bounds of array.
}
}
int main(){
int i;
int table[MAX];
int counts[21]={0}; // <<<< need a place to put the result
int len = sizeof table / sizeof(int);
for(i = 0; i < len; i++){
table[i] = random_in_range(0, 20);
}
count_frequency(table, counts, MAX, 21);
for(i = 0; i < 21; i++) {
printf("number %d - frequency %d\n", i, counts[i]);
}
return 0;
}
Output:
number 0 - frequency 3
number 1 - frequency 5
number 2 - frequency 3
number 3 - frequency 6
number 4 - frequency 6
number 5 - frequency 7
number 6 - frequency 3
number 7 - frequency 5
number 8 - frequency 6
number 9 - frequency 9
number 10 - frequency 4
number 11 - frequency 2
number 12 - frequency 6
number 13 - frequency 8
number 14 - frequency 3
number 15 - frequency 4
number 16 - frequency 5
number 17 - frequency 6
number 18 - frequency 6
number 19 - frequency 3
number 20 - frequency 0
So you're saying you have an array of 100 numbers, each ranging from 0-20, and you want to count the occurrences of a SINGLE number within that array? Then this should do:
size_t count_occurrences(int interesting_num, int* array, size_t array_size) {
size_t i, occurrences = 0;
for (i=0; i < array_size; ++i) {
if (array[array_size] == interesting_num) {
++occurrences;
}
}
return occurrences;
}
Technically, you could replace those "size_t"s with unsigned chars, for the number ranges you're talking about, but given the dynamic calculation of len that you attempted, and the use of "MAX", I suspect you may want to increase those ranges at some point. So, I'm erring on the side of a safer, more general implementation.
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;
}