题
我试图产生质数根据用户的投入。这是我迄今为止,但我只是不能似乎图:
Console.Write("Please enter the number of prime numbers you would like to see:");
int numberOfPrimes = Convert.ToInt32(Console.ReadLine());
for (int x = 0; x < numberOfPrimes; x++)
{
for (int a = 2; a <= x ; ++a)
{
bool prime = true;
for (int b = 2; b < a; ++b)
{
if (a % b == 0)
{
prime = false;
}//end if
}//end double nested for
if (prime == true)
{
Console.WriteLine(a);
}//end if
}//end nested for
}//end for
解决方案
您应该能够明白为什么你的结果是错误的,如果你看一下你的循环结构很容易。通过它们一步手(它不会需要很长时间)。
这是你得到你目前的结果的原因是,没有外环(x < numberOfPrimes
)的每次迭代产生的结果 - 它会跳过相当多的迭代,由于路内循环的结构
你真正需要做的是重组的内部循环。您最里面的循环工作正常,并应能发现任何素数。你的第二个循环,但是,应该只测试尚未测试号码。此外,应该停止循环一旦你找到一个素数。
其他提示
您应该构建您的代码更好,它真的很乱你现在做的方式。有如果IsPrime(int x)
是素数,否则为假返回true的方法x
。
然后,生成numberOfPrimes
素数,你可以做这样的事情:
for ( int primeCount = 0, currentPrime = 2; primeCount < numberOfPrimes; ++currentPrime )
if ( IsPrime(currentPrime) )
{
// do whatever you want with currentPrime, like print it
++primeCount;
}
或者使用筛埃拉托塞尼,这是更快的方法的
要找出一个数x
是素数或没有,尝试所有的2
和Sqrt(x)
之间的其因素。为什么只有Sqrt(x)
?因为如果a*b = x
,然后x / b = a
和x / a = b
,所以,你会两次检查一切,并检查东西,你不应该,如果你走到x / 2
甚至x
。
所以,如果你想使用IsPrime(x)
功能是这样的:
// i <= Sqrt(x) <=> i * i <= x
for ( int i = 2; i * i <= x; ++i )
if ( x % i == 0 )
return false;
return true;
但我建议你使用埃拉托色尼的筛子,因为它的速度更快。您还可以优化的东西,所以你不检查偶数,因为偶数从来都不是主要的,除了2(两者以筛网和幼稚的方法)。治疗x = 2时为边缘的情况下,然后开始检查每隔数(3,5,7,9,11等)
你所寻找的被称为“埃拉托色尼的筛。”由于我没有把做人民的功课,这是我想给你的唯一线索。该算法容易地在互联网上找到。
接下来的素数(X) - 是由不能所有素数s为单位devided的数目,是s <= SQRT(X)。 所以,你可以使用函数像
public bool CheckAndAddPrime(int number,List<int> primes)
{
var sqrt = Math.Sqrt(number);
foreach(var prime in primes)
{
if(prime>sqrt) break;
if(number % prime == 0) return false;
}
primes.Add(number);
return true;
}
和比你能得到像素
var primes = new List<int>();
Enumerable.Range(2,int.MaxValue).Where(x => x.CheckAndAddPrime(x,primes)).Take(YouCountOfPrimes);
var primes = Enumerable.Range(1, numberOfPrimes )
.Where(x => x != 1 &&
!Enumerable.Range2, (int)Math.Sqrt(x)).Any(y => x != y && x % y == 0));
static void Main(string[] args)
{
foreach (int no in get_first_k_primes(10))
{
Console.Write(" "+no.ToString() );
}
}
public static List<int> get_first_k_primes(int k)
{
var primes = new List<int>();
primes.Add(2);
int i = 3;
while(primes.Count < k)
{
if(is_prime(i))
primes.Add(i);
i += 2;
}
return primes;
}
public static bool is_prime(int n)
{
if (n % 2 == 0 && n != 2) return false;
int m = (int)Math.Ceiling(Math.Sqrt(n));
for (int i = 3; i < m; i += 2)
{
if (n % i == 0) return false;
}
return true;
}
1.重命名您的变量。
首先,如果这是家庭作业,你会得到不好的分数(如果你的老师值得他的盐),因为你有毫无意义的变量名(是的,甚至 numberOfPrimes
是错误的,应该命名 requiredNumberOfPrimes
. 。当我看到这个变量时,我问自己“这是他想要的数量,还是他已经找到的数量?”)。
其次,它会帮助你了解哪里出了问题。变量应该根据它们所代表的内容进行逻辑命名。如果您无法解释变量代表什么(例如a & b) 那么你可能无法解释你正在用它们做什么。
2.看看你的循环。
for (int x = 0; x < numberOfPrimes; x++)
for循环的结构是 (initialise; 'should I continue?'; 'each loop do this')
. 。因此在你的循环中
- 您将继续直到 x 等于或大于
numberOfPrimes
*. - 每次执行循环时都会加 1
x
.
您确定这是您想要做的吗? x
似乎代表您找到的素数数量。那么为什么不在找到质数时而不是开始循环时增加它呢?
for (int a = 2; a <= x ; ++a)
for (int b = 2; b < a; ++b)
您正在查看 2 到 2 之间的每个整数 x
, , 包括的。对于每个整数 a
, ,您正在查看之间的每个整数 a
和 2 个(含)。你打算用这些整数做什么?
每次你循环你的顶级循环( x
循环),你将开始你的 a
从头开始循环,每次循环时 a
循环你将开始你的 b
从头开始循环。
因此,如果 x
是10,你运行一次(a = 2),然后你再次运行a(a = 2,a = 3),然后你再次运行a(a = 2,a = 3,a = 4),然后...
3.收集结果而不是将它们写入控制台。
var primes = new List<int>();
它是如此容易。当你找到素数时, primes.Add(a);
. 。然后你就知道你找到了多少个素数(primes.Count
),您可以使用素数列表来有效地确定下一个素数,并且如果需要,您可以稍后使用该列表。
一旦你得到i将环路整理出来,你只需要检查B'的sqrt(一),任何更高,你会发现其他的因素第一。