C# 寻找完美数(优化)
作为编程挑战的一部分,我用C#编写了一个程序,以找到一定范围内的完美数字。然而,我意识到,当计算10000以上的完美数字时,速度非常慢。有没有找到完美数的优化方法?我的代码如下:C# 寻找完美数(优化),c#,optimization,number-theory,perfect-numbers,C#,Optimization,Number Theory,Perfect Numbers,作为编程挑战的一部分,我用C#编写了一个程序,以找到一定范围内的完美数字。然而,我意识到,当计算10000以上的完美数字时,速度非常慢。有没有找到完美数的优化方法?我的代码如下: using System; using System.Collections.Generic; using System.Linq; namespace ConsoleTest { class Program { public static List<int> FindDivisors(int i
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleTest
{
class Program
{
public static List<int> FindDivisors(int inputNo)
{
List<int> Divisors = new List<int>();
for (int i = 1; i<inputNo; i++)
{
if (inputNo%i==0)
Divisors.Add(i);
}
return Divisors;
}
public static void Main(string[] args)
{
const int limit = 100000;
List<int> PerfectNumbers = new List<int>();
List<int> Divisors=new List<int>();
for (int i=1; i<limit; i++)
{
Divisors = FindDivisors(i);
if (i==Divisors.Sum())
PerfectNumbers.Add(i);
}
Console.Write("Output =");
for (int i=0; i<PerfectNumbers.Count; i++)
{
Console.Write(" {0} ",PerfectNumbers[i]);
}
Console.Write("\n\n\nPress any key to continue . . . ");
Console.ReadKey(true);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
名称空间控制台测试
{
班级计划
{
公共静态列表FindDivisor(int inputNo)
{
列表除数=新列表();
对于(int i=1;i完全数会改变吗?不会。当然,它们应该计算一次,然后存储。
在你的情况下,唯一的结果是
6
28
496
8128
下一个是33550336。超出您的范围。解决此类问题的一种方法是在每个数字的内存中构建一个巨大的数组,然后将数字划掉。使用公式
testPerfect = 2n-1(2n - 1)
testPerfect=2n-1(2n-1)
要生成可能性,请检查数字是否完美
这是我最明显的一点:你不需要检查每一个除数。没有必要通过inputNo/2
查找除数。这可以减少一半的计算量,但这并不是一个数量级更快。如果你仍然在寻找计算完美数的方法的话。
这很快就通过了前一万个,但3300万个数字要慢一点
public class Perfect {
private static Perfect INSTANCE = new Perfect();
public static Perfect getInstance() {
return INSTANCE;
}
/**
* the method that determines if a number is perfect;
*
* @param n
* @return
*/
public boolean isPerfect(long n) {
long i = 0;
long value = 0;
while(++i<n){
value = (0 == n%i?value+i:value);
}
return n==value;
}
}
公共类完美{
private static Perfect INSTANCE=new Perfect();
公共静态完美getInstance(){
返回实例;
}
/**
*确定数字是否完美的方法;
*
*@param n
*@返回
*/
公共布尔值isPerfect(长n){
长i=0;
长值=0;
虽然(++i对于任何对基于LINQ的方法感兴趣的人来说,下面的方法在确定调用方提供的整数值是否是一个完美的数字方面非常有效
bool IsPerfectNumber(int value)
{
var isPerfect = false;
int maxCheck = Convert.ToInt32(Math.Sqrt(value));
int[] possibleDivisors = Enumerable.Range(1, maxCheck).ToArray();
int[] properDivisors = possibleDivisors.Where(d => (value % d == 0)).Select(d => d).ToArray();
int divisorsSum = properDivisors.Sum();
if (IsPrime(divisorsSum))
{
int lastDivisor = properDivisors.Last();
isPerfect = (value == (lastDivisor * divisorsSum));
}
return isPerfect;
}
为了简单明了,省略了我在IsPerfectNumber()中使用的IsPrime()实现。从Charles Gargent的答案继续,有一种非常快速的方法可以检查Mersenne数a.k.a.2^n-1是否为素数。它被称为
但基本伪代码(取自维基百科页面)是:
计算完美数字就像计算每周有多少天。结果永远不会改变,所以不要计算。查一查。@Daniel Dyson-海报表明这是某种编程挑战,我怀疑他会对一系列预先计算的答案感到高兴=)@悖论-你还有另一个问题,因为完美数字是如此稀疏,如果你的程序认真搜索完美数字,你会很快突破整数限制。@Joel Goodwin。这是一个公平的观点,但如果我对我的一个团队提出这样的挑战,我希望他们能给出答案,这些应该是毕竟,按照我的理解,挑战在于“找到完美的数字”,而不一定是“计算”它们。如果它们都已经在这个范围内计算过了,为什么还要再计算它们呢?编程就是要找到最佳的解决方案。这并不总是一个算法。@Daniel Dyson。如果我在现实世界的问题中需要它们,解肯定会被存储起来——但对我来说,这个问题的精神是“你怎么能优化这个算法?”这是一件令人讨厌的事情去搜索,虽然,因为它们的分布如此之小,甚至与素数相比。+1,但请注意,这不会找到任何奇数完美数(如果这样的数存在的话)。但在这种情况下不是问题。@balpha您是如何获得上标的?请看:
是白名单上的HTML标记之一,但您必须使用
而不是4-空格缩进的代码块,因为后者在文字上显示HTML标记我使用了生成公式并检查了数字%9==1;:)谢谢!对于那些对balpha的评论感兴趣的人来说,奇数完美数的下限是10**1500。如果这还不够难处理,他们也有一个疯狂的要求列表,他们需要满足,请参见。
// Determine if Mp = 2p − 1 is prime for p > 2
Lucas–Lehmer(p)
var s = 4
var M = 2p − 1
repeat p − 2 times:
s = ((s × s) − 2) mod M
if s == 0 return PRIME else return COMPOSITE