我必须开始学习C作为我正在做的项目的一部分。我已经开始在其中处理'euler'问题并且遇到了first one的问题。我必须找到1000或以下3或5的所有倍数的总和。有人可以帮助我。感谢。
#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);
}
答案 0 :(得分:50)
到目前为止,你已经得到了一些很好的答案,主要是建议:
#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;
}
所以我要采取不同的策略。我知道你这样做是为了学习C,所以这可能有点切线。
真的,你让计算机的工作太难了:)。如果我们提前想出一些事情,它可以使任务更容易。
嗯,3的倍数是多少少于1000?每次有3个进入1000 - 1。
mult 3 =⌊(1000 - 1)/3⌋= 333
(⌊和⌋表示这是 floor 除法,或者,在编程术语中,整数除法,其中余数被删除)。
5的倍数是多少少于1000?
mult 5 =⌊(1000 - 1)/ 5⌋= 199
现在3小于1000的倍数的总和是多少?
sum 3 = 3 + 6 + 9 + ... + 996 + 999 = 3×(1 + 2 + 3 + ... + 332 + 333)= 3×Σ i = 1到mult 3 i
所有5的倍数之和小于1000?
sum 5 = 5 + 10 + 15 + ... + 990 + 995 = 5×(1 + 2 + 3 + ... + 198 + 199)= 5×Σ i = 1到mult 5 i
3的倍数也是5的倍数。这是15的倍数。 因为那些计数到mult 3 和mult 5 (因此sum 3 和sum 5 )我们需要知道mult 15 和sum 15 以避免计算两次。
mult 15 =⌊(1000 - 1)/ 15⌋= 66
sum 15 = 15 + 30 + 45 + ... + 975 + 990 = 15×(1 + 2 + 3 + ... + 65 + 66)= 15×Σ i = 1到mult 15 i
因此问题解决方案“find the sum of all the multiples of 3 or 5 below 1000”就是
soln = sum 3 + sum 5 - sum 15
所以,如果我们想,我们可以直接实现这个:
#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;
}
但我们可以做得更好。为了计算各个和,我们有Gauss's identity表示从1到n的总和(又名Σ i = 1到n i)是n×(n + 1)/ 2,所以:
sum 3 = 3×mult 3 ×(mult 3 +1)/ 2
sum 5 = 5×mult 5 ×(mult 5 +1)/ 2
sum 15 = 15×mult 15 ×(mult 15 +1)/ 2
(注意我们可以在这里使用正常除法或整数除法 - 因为n或n + 1中的一个必须可被2整除,所以无关紧要)
现在这有点整洁,因为这意味着我们可以在不使用循环的情况下找到解决方案:
#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;
}
当然,既然我们已经走了这么远,我们可以手工制作整个事情:
和 3 = 3×333×(333 + 1)/ 2 = 999×334/2 = 999×117 = 117000 - 117 = 116883
和 5 = 5×199×(199 + 1)/ 2 = 995×200/2 = 995×100 = 99500
总和 15 = 15×66×(66 + 1)/ 2 = 990×67/2 = 495×67 = 33165
soln = 116883 + 99500 - 33165 = 233168
写一个更简单的程序:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("233168\n");
return 0;
}
答案 1 :(得分:17)
你可以改变你的ifs:
if ((start % 3 == 0) || (start % 5 == 0))
sum += start;
start ++;
并且不要忘记用零初始化你的总和并从一开始。 另外,将while条件更改为&lt; 1000。
答案 2 :(得分:6)
你可以通过for循环更好地服务,并结合你的条件。
未经测试:
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;
}
答案 3 :(得分:3)
对,好吧,我可以大致看到你要去的地方,我想以前唯一有问题的就是前面提到的。我之前做过这个问题,显然你需要逐步完成3和5的每个倍数并求它们。我这样做了它确实有效:
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);
编辑:还要注意它不是0到1000(含),&lt;因为它是1000以下的最后一个数字,因此在999处停止了1000次,你已经通过&lt; 1001表示你一直到1000,这是5的倍数,这意味着你的答案将比它应该高1000。
答案 4 :(得分:3)
答案都很好,但不会帮助你学习C.
您真正需要了解的是如何找到自己的错误。调试器可以帮助您,C中最强大的调试器称为“printf”。你想知道你的程序在做什么,你的程序不是一个“黑匣子”。
你的程序已打印出总和,这可能是错误的,你想知道原因。例如:
printf("sum:%d start:%d\n", sum, start);
而不是
printf("%d\n", sum);
并将其保存到文本文件中,然后尝试了解出现了什么问题。
答案 5 :(得分:2)
你还没有说出该计划应该做什么,或者你的问题是什么。这使得很难提供帮助。
猜测一下,你真的应该将start和sum初始化为零,也许printf应该在循环之外。
答案 6 :(得分:2)
你真的需要一个调试器,并单步执行代码,以便你可以看到它实际上在做什么。你的基本问题是控制流不是你想象的那样,而不是像其他人那样提供正确的代码,我会试着解释你的代码做了什么。这是发生的事情,一步一步(我已经对行编号):
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: }
你知道这是怎么回事吗?您似乎认为在第4行,在执行sum += 1
之后,控件会回到循环的顶部。它不会,它会在“if / else”构造之后进行下一步。
答案 7 :(得分:2)
您忘记初始化变量
答案 8 :(得分:1)
您的代码存在的问题是您将'start'变量递增两次。这是因为有两个if..else语句。你需要的是一个if..else if..else语句:
if (start % 3 == 0) {
sum = sum + start;
start += 1;
}
else if (start % 5 == 0) {
sum = sum + start;
start += 1;
}
else {
start += 1;
}
或者您可以更简洁,并按如下方式编写:
if(start % 3 == 0)
sum += start;
else if(start % 5 == 0)
sum += start;
start++;
这两种方式中的任何一种都适合你。
祝你好运!答案 9 :(得分:0)
这是一个适用于任意数量因素的通用解决方案:
#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;
}