【问题标题】:Project Euler - Number 2 - C#欧拉计划 - 2 号 - C#
【发布时间】:2017-12-20 04:47:13
【问题描述】:

我是 C# 编程的新手,我认为尝试欧拉问题作为入门基础是一个好主意。但是,我已经到了无法获得问题 2 正确答案的地步。

“斐波那契数列中的每一项新项都是通过将前两项相加生成的。从 1 和 2 开始,前 10 项将是:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

通过考虑斐波那契数列中值不超过四百万的项,求偶数项之和。”

我的代码是这样的:

int i = 1;
int j = 2;
int sum = 0;

while (i < 4000000) 
{
     if (i < j)
     {
         i += j;

         if (i % 2 == 0)
         {
             sum += i;
         }

     }

     else
     {
         j += i;

         if (j % 2 == 0)
         {
             sum += j;
         }
     }
}

MessageBox.Show("The answer is " + sum);

基本上,我认为我只获取序列的最后两个偶数并将它们相加 - 但我不知道如何获取序列的所有偶数并将它们相加。在尝试从我的起点取得进展的同时,有人可以帮助我吗?

附: - 如果有任何非常糟糕的布局选择,请说现在消除这些将帮助我将来成为更好的程序员:)

非常感谢。

【问题讨论】:

  • 我看不出有什么问题。我建议放入调试语句,然后将输出添加到您的问题中。例如:每次循环后输出 i、j 和 sum。
  • 为方便起见:projecteuler.net/problem=2
  • 重新检查。 1)这不是 int 溢出 2)您只检查每个第二个元素的结束条件,但这也不是您的问题的原因。
  • 您只在循环顶部测试 i>4000000。但是有可能 i 或 j 在计算它们的下一个值之后可能会超过该值,然后将超出范围的值添加到 sum 中。您应该在计算下一个新值之后,但在更新总和之前测试是否终止。
  • @hatchet 虽然这是一个错误,但他很幸运,这个特定的截止点没有击中它,因为超过限制的数字是奇数。

标签: c# math


【解决方案1】:

我刚刚登录我的 Project Euler 帐户,查看正确答案。正如其他人所说,您忘记添加初始项 2,但否则您的代码是可以的(正确答案是您的代码输出 + 2),做得很好!

虽然这很令人困惑,但我认为如果您使用 3 个变量,它看起来会更清晰,例如:

int first = 1;
int second = 1;
int newTerm = 0;
int sum = 0;

while (newTerm <= 4000000) 
{
    newTerm = first + second;

    if (newTerm % 2 == 0)
    {
         sum += newTerm;
    }

    first = second;
    second = newTerm;
}

MessageBox.Show("The answer is " + sum);

【讨论】:

  • 非常感谢!我非常感谢您的帮助。
【解决方案2】:

您需要将 sum 的初始值设置为 2,因为您没有将其包含在当前代码的 sum 中。

此外,虽然它在内存使用方面的效率可能较低,但我可能会编写类似这样的代码,因为 IMO 它更具可读性:

var fibonacci = new List<int>();

fibonacci.Add(1);
fibonacci.Add(2);

var curIndex = 1;

while(fibonacci[curIndex] + fibonacci[curIndex - 1] <= 4000000) {
    fibonacci.Add(fibonacci[curIndex] + fibonacci[curIndex - 1]);
    curIndex++;
}

var sum = fibonacci.Where(x => x % 2 == 0).Sum();

【讨论】:

  • 这个解决方案看起来确实有点令人困惑,因为我实际上并不了解 LINQ。您是否建议尽早尝试将 LINQ 作为 C# 的基础?不过非常感谢您的帮助!
  • LINQ 并没有那么复杂。如果您了解 SQL,它基本上只是一个 C# 版本的 SQL,我用它来“查询”上述代码中的列表(您还可以将它用于除内存列表之外的许多其他数据源)。
  • 但是,我会说,如果你打算做更多的 Project Euler 问题,LINQ 会非常有用。
【解决方案3】:

使用数组fib 来存储序列。它更容易编码和调试。在每次迭代中,您只需要检查该值是否为偶数。

fib[i] = fib[i - 1] + fib[i - 2];
if (fib[i] > 4000000) break;
if (fib[i] % 2 == 0) sum += fib[i];

【讨论】:

    【解决方案4】:

    几年前我已经解决了这个问题,所以我不记得我是如何做到的,但我确实可以访问讨论它的论坛。一些提示和彻底的解决方案。数字以一种模式重复。两个赔率后跟一个偶数。因此,您可以跳过数字而不必进行模数运算。

    建议的 C# 解决方案是

            long sum = 0, i0, i1 = 1, i2 = 2;
            do
            {
                sum += i2;
                for (int i = 0; i < 3; i++)
                {
                    i0 = i1;
                    i1 = i2;
                    i2 = i1 + i0;
                }
            } while (i2 < 4000000);
    

    【讨论】:

      【解决方案5】:

      你的代码有点难看,因为你在 i 和 j 之间交替。通过使用三个变量并始终保持它们的含义相同,有一种更简单的方法来计算斐波那契数。

      一个相关的错误是您只在每第二次迭代和错误的地方检查结束条件。但是你很幸运,截止值适合你的错误(超过限制的数字是奇数),所以这不是你的问题。

      另一个错误是您使用&lt; 而不是&lt;= 进行检查,但由于没有斐波那契数等于截止值,这不会导致您的问题。

      这也不是 int 溢出。

      剩下的是您忘记查看序列的前两个元素。只有其中一个是偶数,因此您需要将2 添加到结果中。

      int sum = 0; => int sum = 2;
      

      我个人会编写一个返回无限斐波那契数列的函数,然后使用 Linq 进行过滤和求和。 Fibonacci().TakeWhile(i=&gt; i&lt;=4000000).Where(i=&gt;i%2==0).Sum()

      【讨论】:

        【解决方案6】:

        我使用了一个类来表示一个斐波那契数,我认为这使代码更具可读性。

        public class FibonacciNumber
        {
            private readonly int first;
            private readonly int second;
        
            public FibonacciNumber()
            {
                this.first = 0;
                this.second = 1;
            }
        
            private FibonacciNumber(int first, int second)
            {
                this.first = first;
                this.second = second;
            }
        
            public int Number
            {
                get { return first + second; }
            }
        
            public FibonacciNumber Next
            {
                get
                {
                    return new FibonacciNumber(this.second, this.Number);
                }
            }
        
            public bool IsMultipleOf2
            {
                get { return (this.Number % 2 == 0); }
            }
        }
        

        也许这一步太远了,但最终结果是一个函数,恕我直言:

        var current = new FibonacciNumber();
        var result = 0;
        while (current.Number <= max)
        {
            if (current.IsMultipleOf2)
                result += current.Number;
        
            current = current.Next;
        }
        return result;
        

        但是,它不会像其他没有在 while 循环中更新类的解决方案那样有效。我猜这取决于您的要求,对我来说,我只是想解决问题并继续下一个问题。

        【讨论】:

          【解决方案7】:

          您好,我已经解决了这个问题,请检查它是否正确。 我的代码是,

                    #include<iostream.h>
                    #include<conio.h>
                    class euler2
                      {
                        unsigned long long int a;
                       public:
                      void evensum();
                      };
                   void euler2::evensum()
                    {
                       a=4000000;
                       unsigned  long long int i;
                       unsigned long long int u;
          
                       unsigned long long int initial=0;
                       unsigned long long  int initial1=1;
                       unsigned long long int sum=0;
                    for(i=1;i<=a;i++)
                       {
                            u=initial+initial1;
                            initial=initial1;
                            initial1=u;
                          if(u%2==0)
                             {
          
                           sum=sum+u;
                              }
                         }
                     cout<<"sum of even fibonacci numbers upto 400000 is"<<sum;
                   }
          
                       void main()
                           {
                              euler2 a;
                              clrscr();
                              a.evensum();
                              getch();
                            }
          

          【讨论】:

            【解决方案8】:

            这是我的实现:

            public static int evenFibonachi(int n)
                    {
                        int EvenSum = 2, firstElem = 1, SecondElem = 2, SumElem=0;
            
                        while (SumElem <= n)
                        {
                            swich(ref firstElem, ref SecondElem, ref SumElem);
                            if (SumElem % 2 == 0)
                                EvenSum += SumElem;
                        }
            
                        return EvenSum;
                    }
            
                    private static void swich(ref int firstElem, ref int secondElem, ref int SumElem)
                    {
                        int temp = firstElem;
                        firstElem = secondElem;
                        secondElem += temp;
                        SumElem = firstElem + secondElem;
                    }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多