Not understand this recursive function that inverts digits of a number - c

I found this code
#include <stdio.h>
#include <math.h>
int rev(int num)
{
if(num < 10)
return num;
else
return (num % 10) * pow(10, (int)log10(num)) + rev(num/10);
}
int main(void)
{
printf("%d\n", rev(12345));
return 0;
}
And I set out to analyzing it, but now I have one doubt it is the following, to return to the starting point what values are obtained with (num % 10) according to my understanding should be (1,2,3,4,5) but when trying do the calculation manually I do not get the expected value.
What happens here, if someone explains to me this, or I missed out something?

int rev(int num) // num = 12345
{
if(num < 10) // false
return num;
else
return (num % 10) * pow(10, (int)log10(num)) + rev(num/10);
// (12345 % 10) * 10 ^ (log 12345) + rev(12345/10);
// 5 * 10 ^ (4) + rev (1234)
// 50000 + rev(1234)
}
Based on this, we can assume that:
rev(12345) = 50000 + rev(1234)
rev(1234) = 4000 + rev(123)
rev(123) = 300 + rev(12)
rev(12) = 20 + rev(1)
rev(1) = 1
So, the end result is:
rev(12345) = 50000 + 4000 + 300 + 20 + 1 = 54321
It is a simple math, the only non trivial rule is (int)log10(num), but it was explained by #QuestionC in his comment.

Related

CS50 Credit: Luhn's Algorithm - Please assist

I'm a beginner in CS50 trying to do the Credit problem from Problem Set 1. We are using C. The problem asks us to validate credit card numbers using Luhn's algorithm. I was going to use an array, but code using one wasn't easy to understand for me.
I'm trying to type out the full Luhn formula to calculate. I don't know where I'm messing up. Every time I run a card number that's supposed to be valid, it's never card_total % 10 = 0 like it should be.
Example Card Number: 4003600000000014 => checksum total (int card_total) = 33
Below is just code that asks for the credit card number, runs it through the algorithm, and prints out the total checksum just for me to see if it's working properly. I know this is really long, but this is just for my understanding of all the pieces. I've written much shorter and nicer code before. I swear!
EDIT: I run my code in the cs50 VS virtual codespace, which uses Linux I think. I will take the advice of changing the other ints to longs and see if this fixes my problem. My formulas are consistent, so this is a formatting issue. Once this is fixed, the rest of the problem is easy to solve.
Someone mentioned my complicated calculations. Sorry. I know this could be more brief, but I just wanted to follow the algorithm so I can see what's going on. The lecture for this week didn't touch on going through arrays or manipulating strings, so I'm just doing what I know so far in C. This would be a lot easier in python.
EDIT 2: All that needed to change was int to long. The code now works perfectly and incorporates properly with the rest of my code checking for Amex, Visa, etc. THANK YOU SO MUCH!
#include <cs50.h>
#include <stdio.h>
int get_number(void);
int main(void)
{
long n = get_number();
//calculating card number with modulo
long a = ((n % 10000000000000000) / 1000000000000000);
long b = ((n % 1000000000000000) / 100000000000000);
long c = ((n % 100000000000000) / 10000000000000);
long d = ((n % 10000000000000) / 1000000000000);
long e = ((n % 1000000000000) / 100000000000);
long f = ((n % 100000000000) / 10000000000);
long g = ((n % 10000000000) / 1000000000);
long h = ((n % 1000000000) / 100000000);
long i = ((n % 100000000) / 10000000);
long j = ((n % 10000000) / 1000000);
long k = ((n % 1000000) / 100000);
long l = ((n % 100000) / 10000);
long m = ((n % 10000) / 1000);
long ene = ((n % 1000) / 100);
long o = ((n % 100) / 10);
long p = ((n % 10) / 1); //The "/ 1" is just for visualization
// multiply odd numbers by 2 //Also for visualization
long q = a * 2;
long r = c * 2;
long s = e * 2;
long t = g * 2;
long u = i * 2;
long v = k * 2;
long w = m * 2;
long x = o * 2;
//process odd products //Luhn's has exceptions for double digit numbers
long qq;
if (q < 10)
{
qq = ((q % 10) + ((q % 100)/10));
}
else if (q > 10)
{
qq = (q % 10) + 1;
}
else if (q == 10)
{
qq = 1;
}
else
{
qq = q;
}
long rr;
if (r < 10)
{
rr = ((r % 10) + ((r % 100) / 10));
}
else if (r > 10)
{
rr = (r % 10) + 1;
}
else if (r == 10)
{
rr = 1;
}
else
{
rr = r;
}
long ss;
if (s < 10)
{
ss = ((s % 10) + ((s % 100) / 10));
}
else if (s > 10)
{
ss = (s % 10) + 1;
}
else if (s == 10)
{
ss = 1;
}
else
{
ss = s;
}
long tt;
if (t < 10)
{
tt = ((t % 10) + ((t % 100) / 10));
}
else if (t > 10)
{
tt = (t % 10) + 1;
}
else if (t == 10)
{
tt = 1;
}
else
{
tt = t;
}
long uu;
if (u < 10)
{
uu = ((u % 10) + ((u % 100) / 10));
}
else if (u > 10)
{
uu = (u % 10) + 1;
}
else if (u == 10)
{
uu = 1;
}
else
{
uu = u;
}
long vv;
if (v < 10)
{
vv = ((v % 10) + ((v % 100) / 10));
}
else if (v > 10)
{
vv = (v % 10) + 1;
}
else if (v == 10)
{
vv = 1;
}
else
{
vv = v;
}
long ww;
if (w < 10)
{
ww = ((w % 10) + ((w % 100) / 10));
}
else if (w > 10)
{
ww = (w % 10) + 1;
}
else if (w == 10)
{
ww = 1;
}
else
{
ww = w;
}
long xx;
if (x < 10)
{
xx = ((x % 10) + ((x % 100) / 10));;
}
else if (x > 10)
{
xx = (x % 10) + 1;
}
else if (x == 10)
{
xx = 1;
}
else
{
xx = x;
}
//Sum processed odd products
long total_odd = qq + rr + ss + tt + uu + vv + ww + xx;
//sum total odd products and even card numbers
long bb = ((b % 10) + ((b % 100) / 10));
long dd = ((d % 10) + ((d % 100) / 10));
long ff = ((f % 10) + ((f % 100) / 10));
long hh = ((h % 10) + ((h % 100) / 10));
long jj = ((j % 10) + ((j % 100) / 10));
long ll = ((l % 10) + ((l % 100) / 10));
long eneene = ((ene % 10) + ((ene % 100) / 10));
long pp = ((p %10) + ((p % 100) / 10));
long total_even = bb + dd + ff + hh+ jj + ll + eneene + pp;
//sum odd & even
long card_total = total_odd + total_even;
printf(" %li\n", card_total);
}
int get_number(void) //Works perfectly
{
long n;
do
{
n = get_long("Number: "); // Records credit card number
}
while (n < 1000000000000 || n > 5599999999999999); // CC at least 13 digits but < 17 digits
return n;
}
Trying out your code and debugging it, the issue I found right away is that the return size element for your "get_number" function is too small.
int get_number(void);
When I debugged the returned value to the main function, the value was a negative number since the integer return value is too small for your long integer.
Changing the function definition to "long get_number(void)" in the prototype and the function, allowed for the entered value to flow back to the main function and get tested properly. Following was the test output on my terminal (FYI, I added a couple of printf statements to illustrate that the entered value was flowing through properly).
#Vera:~/C_Programs/Console/CC_Luhn/bin/Release$ ./CC_Luhn
Number: 4003600000000014
Value stored is: 4003600000000014
Returned number: 4003600000000014
20
Just as a double-check, I ran a Luhn calculator program I had built some time back to answer a similar problem. Following is the output again using your credit card example as input.
#Vera:~/C_Programs/Console/Luhn/bin/Release$ ./Luhn
Enter a number: 4003600000000014
Length of number is: 16
Digit is: 4 Value is: 8 Sum is 8
Digit is: 0 Value is: 0 Sum is 8
Digit is: 0 Value is: 0 Sum is 8
Digit is: 3 Value is: 3 Sum is 11
Digit is: 6 Value is: 3 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 0 Value is: 0 Sum is 14
Digit is: 1 Value is: 2 Sum is 16
Digit is: 4 Value is: 4 Sum is 20
Valid
The result of the final calculation was the value of "20" which is a number that ends in zero, which indicates a valid number.
This might have been a bit verbose, but the bottom line is be careful mixing your integer sizes in functions and formulas.
Give that a try to see if it meets the spirit of your project.

Why do i keep getting an invalid feedback?

I've been working on the cs50 pset1 credit for the past 36 hours.
My code is not generating any errors but when i enter my card details it shows invalid, what could be the problem.
I'm a noob, guys please help out.
#include <stdio.h>
#include <cs50.h>
int main (void)
{
long long ccnumber;
do
{
//Prompting the user for his creditcard number
ccnumber=get_long_long("What is your creditcard number\n");
}
while (ccnumber<= 0);
//validating the credit card number to ascertain if its upto 13. 14 or 16
long long numbers = ccnumber;
int totaldigits = 0;
while (numbers > 0)
{
numbers = numbers/10;
totaldigits++;
}
if(totaldigits != 13 || totaldigits !=14 || totaldigits !=16)
{
printf("Invalid\n");
}
//Starting from the second to last digit
//And multiplying through by 2
int number1 = ((ccnumber/10) % 10) *2;
int number2 = ((ccnumber/1000) % 10) *2;
int number3 = ((ccnumber/100000) % 10) *2;
int number4 = ((ccnumber/10000000) % 10) *2;
int number5 = ((ccnumber/1000000000) % 10) *2;
int number6 = ((ccnumber/100000000000) % 10) *2;
int number7 = ((ccnumber/10000000000000) % 10) *2;
int number8 = ((ccnumber/10000000000000000) % 10) *2;
//Getting the Sum of the first number series
int sum1;
sum1 = (number1 + number2 + number3 + number4 + number5 + number6 + number7 + number8);
//Populating the second number series
int number9 = ccnumber % 10;
int number10 = ((ccnumber/100) % 10);
int number11 = ((ccnumber/10000) % 10);
int number12 = ((ccnumber/1000000) % 10);
int number13 = ((ccnumber/100000000) % 10);
int number14 = ((ccnumber/10000000000) % 10);
int number15 = ((ccnumber/1000000000000) % 10);
int number16 = ((ccnumber/100000000000000) % 10);
int sum2;
sum2 =(number9 + number10 + number11 + number12 + number13 + number14 + number15 + number16);
//Adding sum1 and sum2
int checksum;
checksum = sum1 + sum2;
if (checksum % 10 != 0)
{
printf("invalid/n");
}
//Verifying for visacard(1)
if(totaldigits == 13)
{
printf("Visa\n");
}
// Verifying for visa(2)
if(totaldigits == 16)
{
long long visa;
visa = ccnumber/1000000000000000;
if(visa!=4)
{
printf("Invalid\n");
}
else
{
printf("VISA\n");
}
//Verifying for MasterCard
long long master;
master = ccnumber/100000000000000;
if(master!=51 || master!=52 ||master!=53 ||master!=54 ||master!=55)
{
printf("Invalid\n");
}
else
{
printf("MASTER\n");
}
}
//Verifying for Amex
}
/counter
What is your creditcard number
2221000000000009
Invalid
invalid/nInvalid
Invalid
First of all, some of your if conditions are wrong. For example,
if(totaldigits != 13 || totaldigits != 14 || totaldigits != 16)
You want to check if the totaldigits is 13 or 14 or 16, but what you check here is if totaldigits is not 13, then print invalid or if totaldigits is not 14 then, print invalid and so on. Hence, it will always print invalid. You need to use && (AND) instead of || (OR).
The same problem exists in this line as well.
if(master!=51 || master!=52 ||master!=53 ||master!=54 ||master!=55)
Another problem is that you put 1 unnecessary 0 to division in this line, so it always yields 0.
int number8 = ((ccnumber/10000000000000000) % 10) *2; // 1 zero unnecessary
As it is suggested in the comments, you may need to consider creating an array for storing individual digits instead of using 16 different integers. When you have an array you can do the divisions in a for loop so that you don't get confused with a lot of zeros.
As an example, you can refer to this link
A solution for cs50's credit card validation problem .

Wanted to check if a credit card number is valid or not

I wanted to check if a credit card number is valid or not but when i run the code, every number I give as input, the output comes as invalid.
The example given below is what I should i do.
Example with David’s Visa: 4003600000000014.
For the sake of discussion, let’s first underline every other digit, starting with the number’s second-to-last digit:
4003600000000014
Okay, let’s multiply each of the underlined digits by 2:
1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2
That gives us:
2 + 0 + 0 + 0 + 0 + 12 + 0 + 8
Now let’s add those products’ digits (i.e., not the products themselves) together:
2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13
Now let’s add that sum (13) to the sum of the digits that weren’t multiplied by 2 (starting from the end):
13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20
, the last digit in that sum (20) is a 0, so David’s card is legit!
#include <stdio.h>
int main()
{
int no;
printf("Visa number: ");`
scanf("%d", &no);
int d_1, d_2, d_3, d_4, d_5, d_6, d_7, d_8, d_9, d_10, d_11, d_12, d_13, d_14, d_15;
d_15 = no%10;
d_14 = ((no%100)/10)*2;
d_13 = (no%1000)/100;
d_12 = ((no%10000)/1000)*2;
d_11 = (no%100000)/10000;
d_10 = ((no%1000000)/100000)*2;
d_9 = (no%10000000)/1000000;
d_8 = ((no%100000000)/10000000)*2;
d_7 = (no%1000000000)/100000000;
d_6 = ((no%10000000000)/1000000000)*2;
d_5 = (no%100000000000)/10000000000;
d_4 = ((no%1000000000000)/100000000000)*2;
d_3 = (no%10000000000000)/1000000000000;
d_2 = ((no%100000000000000)/10000000000000)*2;
d_1 = (no%1000000000000000)/100000000000000;
int d[7] = {d_2, d_4, d_6, d_8, d_10, d_12, d_14};
int n,add;
for (n=1; n<=7; n++)
if(d[n]>10)
{
d[n] = (d[n]%10);
d[(15-n)+1] = ((d[n]%100)/10);
int sum=0;
for (int i=0; i<7; i++)
sum += d[i];
}
else
{
add = d_14 + d_12 + d_10 + d_8 + d_6 + d_4 + d_2;
}
int sum = add + d_15 + d_13 + d_11 + d_9 + d_7 + d_5 + d_3 + d_1;
if ((sum % 10) == 0)
{
printf("%s\n", "The card is valid");
}
else
{
printf("%s\n", "The card is invalid");
}
}
every number I give as input, the output comes as invalid.
Too big
OP's int is likely 32-bit.
Reading text input that would attempt to form an int outside the int range is undefined behavior. Rest of code is irrelevant.
int no;
scanf("%d", &no); // attempt to read "4003600000000014" leads to UB.
Consider reading user input into a string first and then process the characters. #Weather Vane
char buf[100];
if (fgets(buf, sizeof buf, stdin)) {
int i;
sum[2] = { 0, 0 }; // sums of even indexed digits and odd indexed digits.
// Note: only 1 sum really needed, but using 2 sums to mimic OP's approach
for (i = 0; isdigit((unsigned char) buf[i]); i++) {
digit = buf[i] - '0';
if (i%2 == 0) {
digit *= 2;
if (digit >= 10) {
digit = (digit/10 + digit%10);
}
}
sum[i%2] += digit;
}
// reject bad input: too long or missing expected end
if (i > 16 || (buf[i] != '\n' && buf[i] != '\0')) {
puts("Bad input");
} else {
// pseudo code to not give everything away.
// do math on sum[0], sum[1]
// if as expected --> success
}
}
#include <stdio.h>
#include <cs50.h>
long credit;
int getting_the_final_total_number (void);
void checking_which_kind (void);
int main(void)
{
credit = get_long("Number: ");
int i = 0;
long number_count = credit;
//finding how many numbers are there.
while(number_count > 0)
{
number_count /= 10;
i++;
}
//we use and because (using or make once true, the code block will work and always telling INVALID)
if(i != 13 && i != 15 && i != 16)
{
printf("INVALID\n");
return 0;
}
int total = getting_the_final_total_number(); //adding sum_1 and sum_2
if(total % 10 != 0)
{
printf("INVALID\n");
return 0;
}
checking_which_kind();
}
//assigning the credit to another variable for the loop
int getting_the_final_total_number (void)
{
long credit_one = credit;
int mod_1;
int mod_2;
int sum_1 = 0;
int m;
int d;
int sum_2 = 0;
do
{
//cutting the number into two pieces with all the last numbers and all the second-last-numbers
//cutting the last numbers.
mod_1 = credit_one % 10;
credit_one = credit_one / 10;
sum_1 += mod_1;
//cutting the second-last-numbers.
mod_2 = credit_one % 10;
credit_one = credit_one / 10;
//doubling the mod_2 (the second-last-numbers)
mod_2 = mod_2 * 2;
//making them into one number (if there is 16 or 18 in the product then make them 1 and 6 or 1 and 8. After that add them all together ).
m = mod_2 % 10; //This is for only one standing numer like 1 or 2 or 9 etc (but no 12 or 14 or 16)
d = mod_2 / 10; //This is for ten's digit to make sure to become ONE standing digit
sum_2 = sum_2 + m + d;
}
while(credit_one > 0);
return sum_1 + sum_2;
}
//checking the first two number of credit
void checking_which_kind (void)
{
long cc = credit;
do
{
cc = cc / 10;
}
while(cc > 100);
if(cc / 10 == 5 && (cc % 10 > 0 || cc % 10 < 6))
{
printf("MASTERCARD\n");
}
else if(cc / 10 == 3 && (cc % 10 == 4 || cc % 10 == 7))
{
printf("AMERICAN EXPRESS\n");
}
else if(cc / 10 == 4 && cc % 10 >= 0)
{
printf("VISA\n");
}
else
{
printf("ERROR");
}
}

how to change postition of digits in an integer in c

The problem is as follows:
I need to write a function that takes a four digit integer and then encrypts the number in this manner: take each digit and replace it by (c + 7)% 10;
and then swap the first digit with the third and the second with the last digit;
and then returns the encrypted integer.
I have managed to write this much of code thus far:
#include<stdio.h>
#include <stdlib.h>
#define N 100
int encrypt(int a){
int n=0,i;
for (i=0;i<4;i++){
n = a%10;
a = a/10;
n = (n+7)%10;
}
}
void main()
{
int a;
printf("Enter the four digit integer: ");
scanf("%d",&a);
encrypt(a);
}
I am getting correct output for the conversion but I have no idea how to swap the position of digits.
try this
int encrypt(int num) {
int arr[4];
int i = 0;
arr[0] = (num / 1000);
arr[1] = (num / 100) % 10;
arr[2] = (num / 10) % 10;
arr[3] = num % 10;
for (; i < 4; i++) {
arr[i] = (arr[i] + 7) % 10;
}
return arr[2] * 1000 + arr[3] * 100 + arr[0] * 10 + arr[1];
}
The easiest solution would be:
int encrypt(int value) {
int first = value / 1000;
int second = (value / 100) % 10;
int third = (value / 10) % 10;
int fourth = value % 10;
first = (first + 7) % 10;
second = (second + 7) % 10;
third = (third + 7) % 10;
fourth = (fourth + 7) % 10;
return third * 1000 + fourth * 100 + first * 10 + second;
}
You can do it by taking an array this way:
int encrypt(int a)
{
int i,x[4];
for (i=0;i<4;i++)
{
x[i]=((a%10)+7)%10;
a=a/10;
}
return x[2]+(10*x[3])+(100*x[0])+(1000*x[1]);
}
each digit is represented by 4 bits.
so you can use bit-shift operator to move digists as per your requirement.
n << 8 should move your first digist to the place of third digit
secDig = ((num >> 4 ) & 0x0F) will give your second digit
now secDig << 12 should move your second digit to last [ie 4th digit]
Hope it helps.
so the simple answer is to use bitwise operators << [left shift ], >> [right-shift] and & [ bitwise AND] properly.
Hope it helps
A slight addition to Aleksandar Makragić's answer to take into account the leading zeroes when the return value is <1000, e.g. input: 1234 => output: 0189 or input: 3333 => output: 0000:
printf("Output:\t%04d\n", output);

simple C problem

I have had to start to learning C as part of a project that I am doing. I have started doing the 'euler' problems in it and am having trouble with the first one. I have to find the sum of all multiples of 3 or 5 below 1000. Could someone please help me. Thanks.
#include<stdio.h>
int start;
int sum;
int main() {
while (start < 1001) {
if (start % 3 == 0) {
sum = sum + start;
start += 1;
} else {
start += 1;
}
if (start % 5 == 0) {
sum = sum + start;
start += 1;
} else {
start += 1;
}
printf("%d\n", sum);
}
return(0);
}
You've gotten some great answers so far, mainly suggesting something like:
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
int soln = 0;
for (i = 1; i < 1000; i++)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
soln += i;
}
}
printf("%d\n", soln);
return 0;
}
So I'm going to take a different tack. I know you're doing this to learn C, so this may be a bit of a tangent.
Really, you're making the computer work too hard for this :). If we figured some things out ahead of time, it could make the task easier.
Well, how many multiples of 3 are less than 1000? There's one for each time that 3 goes into 1000 - 1.
mult3 = ⌊ (1000 - 1) / 3 ⌋ = 333
(the ⌊ and ⌋ mean that this is floor division, or, in programming terms, integer division, where the remainder is dropped).
And how many multiples of 5 are less than 1000?
mult5 = ⌊ (1000 - 1) / 5 ⌋ = 199
Now what is the sum of all the multiples of 3 less than 1000?
sum3 = 3 + 6 + 9 + ... + 996 + 999 = 3×(1 + 2 + 3 + ... + 332 + 333) = 3×∑i=1 to mult3 i
And the sum of all the multiples of 5 less than 1000?
sum5 = 5 + 10 + 15 + ... + 990 + 995 = 5×(1 + 2 + 3 + ... + 198 + 199) = 5×∑i = 1 to mult5 i
Some multiples of 3 are also multiples of 5. Those are the multiples of 15.
Since those count towards mult3 and mult5 (and therefore sum3 and sum5) we need to know mult15 and sum15 to avoid counting them twice.
mult15 = ⌊ (1000 - 1) /15 ⌋ = 66
sum15 = 15 + 30 + 45 + ... + 975 + 990 = 15×(1 + 2 + 3 + ... + 65 + 66) = 15×∑i = 1 to mult15 i
So the solution to the problem "find the sum of all the multiples of 3 or 5 below 1000" is then
soln = sum3 + sum5 - sum15
So, if we wanted to, we could implement this directly:
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
int const mult3 = (1000 - 1) / 3;
int const mult5 = (1000 - 1) / 5;
int const mult15 = (1000 - 1) / 15;
int sum3 = 0;
int sum5 = 0;
int sum15 = 0;
int soln;
for (i = 1; i <= mult3; i++) { sum3 += 3*i; }
for (i = 1; i <= mult5; i++) { sum5 += 5*i; }
for (i = 1; i <= mult15; i++) { sum15 += 15*i; }
soln = sum3 + sum5 - sum15;
printf("%d\n", soln);
return 0;
}
But we can do better. For calculating individual sums, we have Gauss's identity which says the sum from 1 to n (aka ∑i = 1 to n i) is n×(n+1)/2, so:
sum3 = 3×mult3×(mult3+1) / 2
sum5 = 5×mult5×(mult5+1) / 2
sum15 = 15×mult15×(mult15+1) / 2
(Note that we can use normal division or integer division here - it doesn't matter since one of n or n+1 must be divisible by 2)
Now this is kind of neat, since it means we can find the solution without using a loop:
#include <stdio.h>
int main(int argc, char *argv[])
{
int const mult3 = (1000 - 1) / 3;
int const mult5 = (1000 - 1) / 5;
int const mult15 = (1000 - 1) / 15;
int const sum3 = (3 * mult3 * (mult3 + 1)) / 2;
int const sum5 = (5 * mult5 * (mult5 + 1)) / 2;
int const sum15 = (15 * mult15 * (mult15 + 1)) / 2;
int const soln = sum3 + sum5 - sum15;
printf("%d\n", soln);
return 0;
}
Of course, since we've gone this far we could crank out the entire thing by hand:
sum3 = 3×333×(333+1) / 2 = 999×334 / 2 = 999×117 = 117000 - 117 = 116883
sum5 = 5×199×(199+1) / 2 = 995×200 / 2 = 995×100 = 99500
sum15 = 15×66×(66+1) / 2 = 990×67 / 2 = 495 × 67 = 33165
soln = 116883 + 99500 - 33165 = 233168
And write a much simpler program:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("233168\n");
return 0;
}
You could change your ifs:
if ((start % 3 == 0) || (start % 5 == 0))
sum += start;
start ++;
and don´t forget to initialize your sum with zero and start with one.
Also, change the while condition to < 1000.
You would be much better served by a for loop, and combining your conditionals.
Not tested:
int main()
{
int x;
int sum = 0;
for (x = 1; x <= 1000; x++)
if (x % 3 == 0 || x % 5 == 0)
sum += x;
printf("%d\n", sum);
return 0;
}
The answers are all good, but won't help you learn C.
What you really need to understand is how to find your own errors. A debugger could help you, and the most powerful debugger in C is called "printf". You want to know what your program is doing, and your program is not a "black box".
Your program already prints the sum, it's probably wrong, and you want to know why. For example:
printf("sum:%d start:%d\n", sum, start);
instead of
printf("%d\n", sum);
and save it into a text file, then try to understand what's going wrong.
does the count start with 1 and end with 999?
does it really go from 1 to 999 without skipping numbers?
does it work on a smaller range?
Eh right, well i can see roughly where you are going, I'm thinking the only thing wrong with it has been previously mentioned. I did this problem before on there, obviously you need to step through every multiple of 3 and 5 and sum them. I did it this way and it does work:
int accumulator = 0;
int i;
for (i = 0; i < 1000; i += 3)
accumulator += i;
for (i = 0; i < 1000; i +=5) {
if (!(i%3==0)) {
accumulator += i;
}
}
printf("%d", accumulator);
EDIT: Also note its not 0 to 1000 inclusive, < 1000 stops at 999 since it is the last number below 1000, you have countered that by < 1001 which means you go all the way to 1000 which is a multiple of 5 meaning your answer will be 1000 higher than it should be.
You haven't said what the program is supposed to do, or what your problem is. That makes it hard to offer help.
At a guess, you really ought to initialize start and sum to zero, and perhaps the printf should be outside the loop.
Really you need a debugger, and to single-step through the code so that you can see what it's actually doing. Your basic problem is that the flow of control isn't going where you think it is, and rather than provide correct code as others have done, I'll try to explain what your code does. Here's what happens, step-by-step (I've numbered the lines):
1: while (start < 1001) {
2: if (start % 3 == 0) {
3: sum = sum + start;
4: start += 1;
5: }
6: else {
7: start += 1;
8: }
9:
10: if (start % 5 == 0) {
11: sum = sum + start;
12: start += 1;
13: }
14: else {
15: start += 1;
16: }
17: printf("%d\n", sum);
18: }
line 1. sum is 0, start is 0. Loop condition true.
line 2. sum is 0, start is 0. If condition true.
line 3. sum is 0, start is 0. sum <- 0.
line 4. sum is 0, start is 0. start <- 1.
line 5. sum is 0, start is 1. jump over "else" clause
line 10. sum is 0, start is 1. If condition false, jump into "else" clause.
line 15. sum is 0, start is 1. start <- 2.
line 16 (skipped)
line 17. sum is 0, start is 2. Print "0\n".
line 18. sum is 0, start is 2. Jump to the top of the loop.
line 1. sum is 0, start is 2. Loop condition true.
line 2. sum is 0, start is 2. If condtion false, jump into "else" clause.
line 7. sum is 0, start is 2. start <- 3.
line 10. sum is 0, start is 3. If condition false, jump into "else" clause.
line 15. sum is 0, start is 3. start <- 4.
line 17. sum is 0, start is 4. Print "0\n".
You see how this is going? You seem to think that at line 4, after doing sum += 1, control goes back to the top of the loop. It doesn't, it goes to the next thing after the "if/else" construct.
You have forgotten to initialize your variables,
The problem with your code is that your incrementing the 'start' variable twice. This is due to having two if..else statements. What you need is an if..else if..else statement as so:
if (start % 3 == 0) {
sum = sum + start;
start += 1;
}
else if (start % 5 == 0) {
sum = sum + start;
start += 1;
}
else {
start += 1;
}
Or you could be more concise and write it as follows:
if(start % 3 == 0)
sum += start;
else if(start % 5 == 0)
sum += start;
start++;
Either of those two ways should work for you.
Good luck!
Here's a general solution which works with an arbitrary number of factors:
#include <stdio.h>
#define sum_multiples(BOUND, ...) \
_sum_multiples(BOUND, (unsigned []){ __VA_ARGS__, 0 })
static inline unsigned sum_single(unsigned bound, unsigned base)
{
unsigned n = bound / base;
return base * (n * (n + 1)) / 2;
}
unsigned _sum_multiples(unsigned bound, unsigned bases[])
{
unsigned sum = 0;
for(unsigned i = 0; bases[i]; ++i)
{
sum += sum_single(bound, bases[i]);
for(unsigned j = i + 1; bases[j]; ++j)
sum -= sum_single(bound, bases[i] * bases[j]);
}
return sum;
}
int main(void)
{
printf("%u\n", sum_multiples(999, 3, 5));
return 0;
}

Resources