C#For循环产生索引超出范围错误

时间:2019-06-29 20:45:34

标签: c# for-loop

我正在尝试解决Project Euler难题46。在此难题中,您必须找到第一个不能由素数和平方的和得出的复合数。

为解决问题,我遍历所有奇数,检查它们是否为质数,如果不是,则遍历数字以下的所有质数,以检查差是否为平方的两倍。

我正在使用两个for循环来执行此操作,由于某种原因,遍历素数的for循环会引发参数超出范围异常。

我不知道为什么会引发此错误,因为for循环不应允许这种情况发生。

这是我的代码:

using System;
using System.Collections.Generic;

namespace Challenge_46
{
    class Program
    {
        /*
         * Task -
         * It was proposed by Christian Goldbach that every odd composite number can be written as the sum of a prime and twice a square.
         * 9 = 7 + 2 × 1^2
         * 15 = 7 + 2 × 2^2
         * 21 = 3 + 2 × 3^2
         * 25 = 7 + 2 × 3^2
         * 27 = 19 + 2 × ^22
         * 33 = 31 + 2 × 1^2
         * 
         * It turns out that the conjecture was false.
         * 
         * What is the smallest odd composite that cannot be written as the sum of a prime and twice a square?
         */
        static void Main(string[] args)
        {
            List<int> primes = new List<int>() { 3 }; // We do not need 2 been as an odd number minus an even number is odd, which cannot be 2 times a square
            bool notFound = true;

            for (int i = 5; notFound == true; i += 2 )
            {
                if (IsPrime(i, primes))
                {
                    primes.Add(i);
                    continue;
                }

                for (int j = 0; primes[j] < i && j < primes.Count; j++)
                {
                    if (!(IsSquare( (i - primes[j]) / 2)))
                    {
                        notFound = false;
                    }
                    else
                    {
                        notFound = true;
                        break;
                    }
                }

                if (notFound == false)
                {
                    Console.WriteLine("The first composite number that cannot be written as the sum of a prime and twice a square is {0}", i);
                }
            }
        }

        static bool IsSquare(int n)
        {
            if (Math.Sqrt(n) == Math.Floor(Math.Sqrt(n))) // if the square root is an integer
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        static bool IsPrime(int n, List<int> primes)
        {
            foreach (int prime in primes)
            {
                if (n % prime == 0)
                {
                    return false;
                }
            }

            return true;
        }
    }
}

我们将不胜感激。

谢谢。

1 个答案:

答案 0 :(得分:3)

您的错误是由for条件下出口评估的顺序引起的。条件是从左到右评估的,因此代码首先评估条件primes[j] < i,只有在此之后,代码才会检查j < primes.Count,但这不会保护第一个评估在j时超出范围等于素数。计数。

修复很容易,只需交换两个条件即可。首先检查您是否仍在范围内,然后检查其他情况

for (int j = 0; j < primes.Count && primes[j] < i; j++)