I have a problem with my algorithm. I can't find where a go wrong in the task below.
Description:
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
Here is my solution in C:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main() {
bool *numbers = (bool *)malloc(sizeof(bool) * 2000000);
unsigned long run = 1;
while (run < 2000000) {
numbers[run] = true;
run++;
}
unsigned long sum = 0;
for (long i = 2; i < 2000000; i++) {
if (numbers[i] == true) {
for (long x = 2 * i; x < 2000000; x += i) {
numbers[x] = false;
}
}
}
run = 0;
while (run < 2000000) {
if (numbers[run] == true) {
sum = sum + run;
}
run++;
}
printf("%d\n", sum-1); // cause 1
free(numbers);
return 0;
}
Thanks for help!!!
The problem in your code is you do not use the correct printf conversion specifier for sum that has type unsigned long: you should write:
printf("%lu\n", sum);
The result, 142913828923 exceeds the range of 32-bit integers, so you should actually use a larger type such as long long which is guaranteed to have at least 63 value bits. The last loop should start from 2 to avoid counting 1 as a prime number.
Here is a modified version with some improvements:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main() {
int limit = 2000000;
bool *numbers = (bool *)malloc(sizeof(bool) * limit);
if (numbers == NULL) {
printf("not enough memory\n");
return 1;
}
for (int run = 0; run < limit; run++) {
numbers[run] = true;
}
for (long long i = 2; i * i < limit; i++) {
if (numbers[i] == true) {
for (long long x = i * i; x < limit; x += i) {
numbers[x] = false;
}
}
}
long long sum = 0;
for (int run = 2; run < limit; run++) {
if (numbers[run] == true) {
sum = sum + run;
}
}
printf("%lld\n", sum);
free(numbers);
return 0;
}
You can try something along these lines:
#include <stdio.h>
#include <stdlib.h>
int main(){
unsigned long int i,j;
unsigned long long sum=0; // the sum is potentially large
unsigned long cnt=0;
int limit=2000000; // the limit for the sums
char *primes; // only needs to be used as a flag holder
primes = malloc(sizeof(char)*limit); // flag of is prime or not
if(primes==NULL) {
perror("main, malloc");
return(-1);
} // else
for (i=2;i<limit;i++) // set the flags to True to start
primes[i]=1;
for (i=2;i<limit;i++) // now go through all combos
if (primes[i]) // already know; no need
for (j=i;i*j<limit;j++) // has i and j as factors
primes[i*j]=0; // not prime
for (i=2;i<limit;i++) // now add them up
if (primes[i]) {
sum+=i;
cnt++;
}
// report what was found; note %lu for long or %llu for long long
printf("There are %lu primes less than %d with a sum of %llu",
cnt, limit, sum);
return 0;
}
You can also invert the search to flag composite numbers rather than primes by using calloc vs malloc and save a loop (Thanks to Anti Haapala):
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main(){
unsigned long i,j;
unsigned long long sum=0; // the sum is potentially large
unsigned long cnt=0;
int limit=2000000; // the limit for the sums
bool * composite = (bool *)calloc(limit, sizeof(bool));
if(composite==NULL) {
perror("main, calloc");
return(-1);
}
for (i=2;i<limit;i++) // now go through all combos
if (!composite[i])
for (j=i;i*j<limit;j++) // has i and j as factors
composite[i*j]=true; // composite; not prime
for (i=2;i<limit;i++) // now add them up
if (!composite[i]) {
sum+=i;
cnt++;
}
// report what was found; note %lu for long
printf("There are %lu primes less than %d with a sum of %llu",
cnt, limit, sum);
return 0;
}
Both print:
There are 148933 primes less than 2000000 with a sum of 142913828922
Note:
Use a long long for the sum which is guaranteed to be 64 bits. While a long may be 32 or 64 bits and an int may be as short as 16 bits. See C data types
Make sure the printf type and length specifiers are correct given the data types being printed.
Related
I'm trying to create a recursive function to reverse digits of a number in C. This is what I've written. It works fine when used one time but when used multiple times it keeps piling the numbers together. I think the problem can be sorted if the sum is initialized to zero each time the function is called but I'm unable to do it. I've tried declaring sum=0 as a global variable but the result was the same.
Input-
12
23
34
45
Output
21
2132
213243
21324354
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int digit_reverse(int N)
{
int rem;
static int sum=0;
if(N>0)
{
rem=N%10;
sum=sum*10+rem;
digit_reverse(N/10);
}
else
return 0;
return sum;
}
int main()
{
int a[25],i;
for(i=0;i<4;i++)
{
scanf("%d", &a[i]);
}
printf("Output\n");
for(i=0;i<4;i++)
{
printf("%d\n",digit_reverse(a[i]));
}
}
Maybe you can write your function without using static variables:
void _digit_reverse(int N, int *sum)
{
int rem;
if (N > 0)
{
rem = N % 10;
*sum = *sum * 10 + rem;
_digit_reverse(N / 10, sum);
}
}
int digit_reverse(int N)
{
int sum = 0;
_digit_reverse(N, &sum);
return sum;
}
Or take the sum outside:
int sum = 0;
int digit_reverse(int N)
{
int rem;
if (N > 0)
{
rem = N % 10;
sum = sum * 10 + rem;
digit_reverse(N / 10);
}
else
return 0;
return sum;
}
int main()
{
int a[25], i;
for (i = 0; i < 4; i++)
{
scanf("%d", &a[i]);
}
printf("Output\n");
for (i = 0; i < 4; i++)
{
sum = 0;
printf("%d\n", digit_reverse(a[i]));
}
}
I believe that the static variable gets initialized only once. This is the problem with your approach.
dude everything looks fine to me if the code do not needs to be reusable I can think of several solutions but keep in mind static and or global variables are not best practices unless necessarily required to.
secondly change your
// from static int sum = 0;
// to
static long sum = 0;
// or
static long long sum = 0;
the reason for this error is value overflow
an integer cannot have more than 4 bytes of data in this specific case you definitly needs more.
I want to solve this problem: https://projecteuler.net/problem=3 by this program, but I'm not sure its true way to use long long int.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
long long int result = factors(6051475143);
printf("%lld", result);
return 0;
}
void factors(int number) {
int factor[100000];
int index = 0, i = 1;
for (; i < number; i++) {
if (number % i == 0) {
factor[index] = i;
index += 1;
}
}
findprime(factor, 100000);
}
int findprime(int prime[], int size) {
int i = 0, j;
long long int latestprime;
for(; i < size; i++) {
if (prime[i] == 0)
break;
int is_prime = 1;
for (j = 2; j < prime[i]; j++) {
if (prime[i] % j == 0 && prime[i] != j) {
is_prime = 0;
break;
}
}
if (is_prime == 1)
latestprime = prime[i];
}
return latestprime;
}
If I try 10-digit number it works but when I try a 12-digit number it returns zero.
To solve this problem, you indeed need a type that is large enough to represent the number. unsigned long long is specified as having at least 64 value bits, which is 18446744073709551615.
Your program has undefined behavior, even for small numbers: result = factors(6051475143) does not reliably store anything useful as factors is defined as a void function and does not even have a return statement. It works by chance because the last statement, findprime(factor, 100000); leaves the return value of findprime in the register where main retrieves what it expects to be the int result of factors(), an return type inferred by the compiler from the lack of prototype.
To find the largest prime factor, you should try factors and reduce the number whenever you find one that divides it evenly.
Here is a modified version:
#include <stdio.h>
unsigned long long largest_factor(unsigned long long number) {
unsigned long long p;
if (number < 2)
return number;
for (p = 2; p * p <= number; p++) {
while (number % p == 0) {
number /= p;
}
}
if (number == 1)
return p;
else
return number;
}
int main(int argc, char *argv[]) {
printf("%llu\n", largest_factor(6051475143));
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main() {
long long int result =factors(6051475143);
printf("%lld",result);
return 0;
}
factors(long long int number)
{
long int factor[1000000];
long long int x;
long int index=0,i=1;
for(;i<800000; i++)
{
if (number%i==0)
{
factor[index] = i;
index+=1;
}
}
x = findprime(factor,index);
return x;
}
int findprime(long int prime[],long int size)
{
long int i = 0,j;
long long int latestprime;
for(;i<size;i++)
{
if (prime[i] == 0)
break;
int is_prime=1;
for(j=2;j<prime[i];j++)
{
if (prime[i]%j==0 && prime[i]!=j)
{
is_prime=0;
break;
}
}
if (is_prime==1)
latestprime = prime[i];
}
return latestprime;
}
I have tried different inputs and when it exceeds a 7 or 8 digit value it just shows some wrong answers as outputs but it worked fine with most of my cases.
#include <stdio.h>
#include <stdlib.h>
int bin(unsigned long long int n){//gave function for binary convertion
if(n==0)
return 0;
else
return (n%2+10*bin(n/2));
}
int main()
{
unsigned long long int n,x;/*I even gave high digit data type*/
int i, v, count=0, max=0;
scanf("%llu",&n); /*if input is >8-digit output is wrong*/
x = bin(n);
v = floor(log10(x))+1; /*Its length*/
int a[v];
for(i = v-1; i >= 0; i--){ /*string it in array*/
a[i] = x%10;
x = x/10;
}
for(i = 0; i < v; i++){
if(a[i] == 0){
count = 0;}
else{
count++;}
if(max < count){
max = count;}
}
printf("%d",max);/*I gave 99999999 output is 8 but its shows 9*/
}
Your program has a number of problems. Here is one example:
int bin(unsigned long long int n){
^^^
The function returns an int so the calculation will overflow for even small numbers:
printf("%d\n", bin(1023)); // will print 1111111111 (fine)
printf("%d\n", bin(1024)); // will/may print 1410065408 (ups - very bad)
Even if you change to
unsigned long long int bin(unsigned long long int n){
overflow will happen soon.
In I'll recommend that you look directly into the binary pattern of the number using the & operator.
I'll not solve the complete task for you but here is some code that may help you.
#include <stdio.h>
#include <stdlib.h>
int main()
{
size_t t = 1;
size_t limit;
size_t n;
if (scanf("%zu", &n) != 1)
{
printf("Illegal input\n");
exit(1);
}
limit = 8 * sizeof n; // Assume 8 bit chars
for (size_t i = 0; i < limit; ++i)
{
if (n & t)
{
printf("Bit %zu is 1\n", i);
}
else
{
printf("Bit %zu is 0\n", i);
}
t = t << 1;
}
return 0;
}
What am i doing wrong here?
#include<stdio.h>
int main(){
int i,count;
long long int sum = 0, num;
for(num = 1; num <= 1000; num++){
count = 0;
for(i = 2; i <= num / 2; i++){
if(num % i == 0){
count++;
break;
}
}
if(count == 0 && num != 1)
sum = sum + num;
}
printf("Sum of prime numbers is: %d ", sum);
return 0;
}
I tried to make a program that outputs the sum of all primes below nth number, n being 2 million however when i try to run it, there is a slight delay and it outputs nothing... it works well enough for small numbers like 1000 or 100 but big numbers it just does not output anything.There are no error or bugs that i know of either. (please help, i know nothing, so guide this young one)
The above program is fine, but it is possible to further reduce the time complexity and make it faster. The better approach is to use sieve of eratosthenes algorithm.You can read about it here http://www.geeksforgeeks.org/sieve-of-eratosthenes/
The program for your problem is
#include <bits/stdc++.h>
using namespace std;
void SieveOfEratosthenes(long long int n)
{
bool prime[n+1];
memset(prime, true, sizeof(prime));
for (long long int p=2; p*p<=n; p++)
{
if (prime[p] == true)
{
for (int i=p*2; i<=n; i += p)
prime[i] = false;
}
}
long long sum=0;
for (int p=2; p<=n; p++)
if (prime[p])
sum+=p;
cout << sum << " ";
}
int main()
{
int n = 2000000;
cout << "sum of prime numbers less then 2000000 is :" << endl;
SieveOfEratosthenes(n);
return 0;
}
Please let me know if you face difficulty in understanding the program.Note: You can also use Segmented seive to further reduce the time complexity
#include<stdio.h>
#include<math.h>
int main(){
int i,count;
long long int sum=0, num;
for(num = 1;num<=1000000;num++){
count = 0;
for(i=2;i<=sqrt(num);i++){ //change here
if(num%i==0){
count++;
break;
}
}
if(count==0 && num!= 1)
sum = sum + num;
}
printf("Sum of prime numbers is: %lld ",sum); //and here
return 0;
}
Some simple maths, while checking for prime, check up to square root of a number. And in printf() the format specifier for long long int is %lld not %d.
This code is designed to find the sum of digits of 100!. I get the correct ouput in ideone but the wrong one in codeblocks. Please help.
#include <stdio.h>
#include <stdlib.h>
#define size_of_number 160
#define question 100
//Function Prototypes
void initialise(int[]);
int sum_of_digits(int[]);
void factorial(int[],int);
int main()
{
int number[size_of_number];
int sum;
initialise(number);
factorial(number, question);
//Getting the sum of the digits of the number
sum = sum_of_digits(number);
printf("The sum of the digits of %d! is %d.\n",question, sum);
return 0;
}
//Initially, the number is 0 so all it's digits are set to zero.
void initialise(int number[])
{
int i;
for(i = 0; i < size_of_number; i++)
{
number[i] = 0;
}
}
//Finding the factorial by multiplying the digits
void factorial(int number[], int num)
{
int i, first_digit;
int carry, replace, product;
first_digit = 0;
number[first_digit] = 1;
while(num != 1)
{
carry = 0;
for(i = 0; i <= first_digit; i++)
{
product = num*number[i] + carry;
replace = product%10;
carry = product/10;
number[i] = replace;
if( (i == first_digit) && (carry > 0) )
{
first_digit++;
}
}
num--;
}
}
//Finding the sum of all digits
int sum_of_digits(int number[])
{
int i, sum;
for(i = 0; i < size_of_number; i++)
{
sum = sum + number[i];
}
return sum;
}
I had problems with some other programs too. Why s Codeblocks not giving the correct output which is 648 ?
You don't initialize sum in the function sum_of_digits. Normal local variables don't automatically get a starting value in C, so your program has what the C standard calls undefined behaviour. Anything can happen, but what typically does happen is that the variable starts with whatever data happened to be in the place in memory where the variable happened to be located.