Hello! I was working on the first project Euler problem which is:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
The solution I came up with was to use a for loop to slowly work through the multiples and test whether or not it was below 1000. If it was the for loop would run again and if not it would end and move to the next set of multiples, slowly adding them together. I came up with this code:
#include "Header.h"
int main() {
int a = 1;
int b = 0;
int c = 0;
for (int test = 0; test = 0;a = a + 1) {
b = a * 3;
if (b < 1000) {
c = c + b;
} else {
test = 1;
}
}
cout << c;
int random;
cin >> random;
return 0;
}
My header file only includes a #include <iostream> and using namespace std;. So I know the problem is not there. For some reason when I run the program, however, it only returns 0 and nothing else. I've tried rewriting some of the functions in different ways but I'm probably just missing something blatantly obvious. Maybe one of you find people could help?
I can't see any check for being a multiple of 5 in your code. You are just adding multiples of 3.
To really overcomplicate it, but if you want your code to run really fast and all you want is the sum, you strictly only need to check up to 3*5 = 15 (plus a few left over at the end). The numbers will repeat modulo 3*5 and you could find how many times this went into 1000-1.
Alternatively, and provided your numbers are coprime (as they are here, but not in general):
- add up the multiples of 3 (use the formula for an arithmetic series rather than looping)
- plus add up the multiples of 5 (ditto)
- minus sum of the multiples of 3*5 = 15 (to avoid double counting)
Gets more complicated if the numbers aren't coprime, but you divide out the HCF from one of them first and get the right result.
#include<iostream>
usingnamespace std;
int sumMultiples( int n, int nMax ) // function to find sum of multiples of n less than OR EQUAL TO nMax
{
int num = nMax / n; // number of whole-number multiples
int first = n; // first term of arithmetic series
int last = num * n; // last term of arithmetic series
return num * ( first + last ) / 2; // sum of arithmetic series (at least one factor is even; integer division not a problem)
}
int main()
{
int m, n, big;
cout << "You will determine the sum of multiples of m and n that are (STRICTLY) less than big" << endl;
cout << "Make sure that m and n are coprime (have no common factors)" << endl;
cout << "Input m, n, big: ";
cin >> m >> n >> big;
cout << "\nSum is " << sumMultiples( m, big - 1 ) + sumMultiples( n, big - 1 ) - sumMultiples( m * n, big - 1 ) << endl;
}
Here are some measurements:
Note: The code posted by lastchance is rewritten to be evaluated at compile-time
(m*n instead of lcm(m,n) works only if m and n are relatively prime; here lcm(3,5) == 3*5).
#include <iostream>
#include <algorithm>
#include <ctime>
struct cpu_timer
{
~cpu_timer()
{
constauto finish = std::clock() ;
std::cout << (finish-start) * 1000.0 / CLOCKS_PER_SEC << " millisecs (processor)\n" ;
};
private: std::clock_t start = std::clock() ;
};
int main()
{
constexprlonglong UBOUND = 400'000'000 ; // numbers less than this
{
std::cout << "one loop with an if (logical or in condition):\n" ;
longlong sum = 0 ;
{
cpu_timer timer ;
for( longlong n = 1 ; n < UBOUND ; ++n ) // for every number from 1 to UBOUND-1
{
if( n%3 == 0 || n%5 == 0 ) sum += n ; // multiple of three or five (or both)
}
}
std::cout << "sum == " << sum << "\n---------------------\n\n" ; ;
}
{
std::cout << "one loop with if - else if construct:\n" ;
longlong sum = 0 ;
{
cpu_timer timer ;
for( longlong n = 1 ; n < UBOUND ; ++n ) // for every number from 1 to UBOUND-1
{
if( n%3 == 0 ) sum += n ;
elseif( n%5 == 0 ) sum += n ; // else if: we don't want to add multiples of 15 twice
}
}
std::cout << "sum == " << sum << "\n---------------------\n\n" ; ;
}
{
std::cout << "three loops: simple, transparent code; no conditionals in the loops)\n""(the optimiser can figure out everything about what is going on):\n" ;
longlong sum = 0 ;
{
cpu_timer timer ;
for( longlong n = 3 ; n < UBOUND ; n += 3 ) sum += n ; // all multiples of three
for( longlong n = 5 ; n < UBOUND ; n += 5 ) sum += n ; // all multiples of five
for( longlong n = 15 ; n < UBOUND ; n += 15 ) sum -= n ; // multiples of 15 have been added twice
}
// so subtract multiples of 15
std::cout << "sum == " << sum << "\n---------------------\n\n" ; ;
}
{
std::cout << "one loop with clever (needlessly clever?) increment:\n" ;
longlong sum = 0 ;
{
cpu_timer timer ;
// where n is a multiple of either three or five (or both)
// the smaller of (3-n%3) and (5-n%5) gives the increment required
// to get to the next higher multiple of three or five (or both)
for( longlong n = 3 ; n < UBOUND ; n += std::min( (3-n%3), (5-n%5) ) ) sum += n ;
}
std::cout << "sum == " << sum << "\n---------------------\n\n" ; ;
}
{
std::cout << "constexpr: demand evaluation at compile time:\n" ;
longlong sum = 0 ;
{
cpu_timer timer ;
// 3 + 6 + ... + 999999999 == 3 * ( 1 + 2 + 3 + ... + 333333333 ) == 3 * 333333333 * 333333334 / 2
constexprlonglong N = UBOUND - 1 ;
constexprlonglong sum3 = 3 * (N/3) * ( N/3 + 1 ) / 2 ; // sum of multiples of three
constexprlonglong sum5 = 5 * (N/5) * ( N/5 + 1 ) / 2 ; // sum of multiples of five
constexprlonglong sum15 = 15 * (N/15) * ( N/15 + 1 ) / 2 ; // sum of multiples of fifteen
sum = sum3 + sum5 - sum15 ;
}
std::cout << "sum == " << sum << "\n---------------------\n\n" ; ;
}
}
echo && echo '===== clang++/libc++ =======' && echo && clang++ -std=c++1z -stdlib=libc++ -Wall -Wextra -pedantic-errors -O3 main.cpp -lsupc++ && ./a.out
echo && echo && echo '===== g++/libstdc++ =======' && echo && g++ -std=c++1z -Wall -Wextra -pedantic-errors -O3 main.cpp && ./a.out
===== clang++/libc++ =======
one loop with an if (logical or in condition):
1460 millisecs (processor)
sum == 37333333266666668
---------------------
one loop with if - else if construct:
1340 millisecs (processor)
sum == 37333333266666668
---------------------
three loops: simple, transparent code; no conditionals in the loops)
(the optimiser can figure out everything about what is going on):
0 millisecs (processor)
sum == 37333333266666668
---------------------
one loop with clever (needlessly clever?) increment:
1380 millisecs (processor)
sum == 37333333266666668
---------------------
constexpr: demand evaluation at compile time:
0 millisecs (processor)
sum == 37333333266666668
---------------------
===== g++/libstdc++ =======
one loop with an if (logical or in condition):
1220 millisecs (processor)
sum == 37333333266666668
---------------------
one loop with if - else if construct:
1050 millisecs (processor)
sum == 37333333266666668
---------------------
three loops: simple, transparent code; no conditionals in the loops)
(the optimiser can figure out everything about what is going on):
0 millisecs (processor)
sum == 37333333266666668
---------------------
one loop with clever (needlessly clever?) increment:
1270 millisecs (processor)
sum == 37333333266666668
---------------------
constexpr: demand evaluation at compile time:
0 millisecs (processor)
sum == 37333333266666668
---------------------
the chrono clocks measure actual time elapsed regardless of which programs are recieving processing time, not time spend by this program on processing.
I don't think @Skoliro realised what he/she had sparked off!
I'll stick with the sum and difference of arithmetic series though - it gives an explicit formula and the number of arithmetic operations is independent of the upper bound (at least as long as m and n are co-prime: finding and taking out the HCF probably makes it more expensive).