简单的C问题

时间:2009-06-18 22:31:04

标签: c

我必须开始学习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);
}

10 个答案:

答案 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);

并将其保存到文本文件中,然后尝试了解出现了什么问题。

  • 计数从1开始,以999结束吗?
  • 在没有跳过数字的情况下真的从1到999?
  • 它适用于较小的范围吗?

答案 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:    }
  • 第1行。和为0,开始为0.循环条件为真。
  • 第2行。和为0,开始为0.如果条件为真。
  • 第3行.sum为0,start为0. sum&lt; -0。
  • 第4行.sum为0,start为0. start&lt; - 1。
  • 第5行。总和为0,开始为1.跳过“else”子句
  • 第10行。总和为0,start为1.如果条件为false,则跳转到“else”子句。
  • 第15行。总和为0,开始为1.开始&lt; - 2。
  • 第16行(跳过)
  • 第17行。总和为0,开始为2.打印“0 \ n”。
  • 第18行.sum为0,start为2.跳转到循环顶部。
  • 第1行。和为0,开始为2.循环条件为真。
  • 第2行.sum为0,start为2.如果condtion为false,则跳转到“else”子句。
  • 第7行。总和为0,开始为2.开始&lt; - 3。
  • 第10行.sum为0,start为3.如果条件为false,则跳转到“else”子句。
  • 第15行。总和为0,开始为3.开始&lt; - 4。
  • 第17行。总和为0,开始为4.打印“0 \ n”。

你知道这是怎么回事吗?您似乎认为在第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;
}