我正在努力尽可能地改进这个有趣的算法。
现在,我有这个:
using System;
class Program
{
static void Main()
{
ulong num, largest_pFact;
uint i = 2;
string strNum;
Console.Write("Enter number: ");
strNum = Console.ReadLine();
num = ulong.Parse(strNum);
largest_pFact = num;
while (i < Math.Sqrt((double) largest_pFact))
{
if (i % 2 != 0 | i == 2) {
if (largest_pFact % i == 0)
largest_pFact /= i;
}
i++;
}
Console.WriteLine("Largest prime factor of {0} is: {1}", num, largest_pFact);
Console.ReadLine();
}
}
所有想法?
谢谢!
编辑:我实施了Ben的算法,感谢eveyone的帮助!
答案 0 :(得分:2)
我有一个更快的算法here。
它消除了平方根并正确处理重复因子。
进一步优化:
static private ulong maxfactor (ulong n)
{
unchecked
{
while (n > 3 && 0 == (n & 1)) n >>= 1;
uint k = 3;
ulong k2 = 9;
ulong delta = 16;
while (k2 <= n)
{
if (n % k == 0)
{
n /= k;
}
else
{
k += 2;
if (k2 + delta < delta) return n;
k2 += delta;
delta += 8;
}
}
}
return n;
}
这是一个有效的演示:http://ideone.com/SIcIL
答案 1 :(得分:1)
- 在一些变量中存储Math.Sqrt((double)largest_pFact),最好是ulong。这避免了每次通过循环时重新计算函数,并且整数比较可能比浮点比较更快。您需要将比较更改为&lt; = but。
- 完全避免在偶数上循环。只需为i = 2包含一个特殊情况,然后在3处以i开始,在每个循环上递增2。你可以更进一步,让i = 2,3是特殊情况,然后只测试i = 6n + 1或6n-1。
答案 2 :(得分:1)
好吧,首先我将特殊情况2移出循环,在整个循环中检查它时没有必要处理它。如果可能,请使用数据类型int
而不是uint
,因为它通常更快:
if (largest_pFact % 2 == 0) {
largest_pFact /= 2;
}
int i = 3;
while (i < Math.Sqrt((double) largest_pFact)) {
if (i % 2 != 0) {
if (largest_pFact % i == 0) {
largest_pFact /= i;
}
}
i++;
}
平方根计算相对昂贵,因此也应事先进行:
if (largest_pFact % 2 == 0) {
largest_pFact /= 2;
}
int i = 3;
int sq = Math.Sqrt((double) largest_pFact);
while (i < sq) {
if (i % 2 != 0) {
if (largest_pFact % i == 0) {
largest_pFact /= i;
}
}
i++;
}
然后我会以两步为增量i
,以消除一个模数检查:
if (largest_pFact % 2 == 0) {
largest_pFact /= 2;
}
int i = 3;
int sq = Math.Sqrt((double) largest_pFact);
while (i < sq) {
if (largest_pFact % i == 0) {
largest_pFact /= i;
}
i += 2;
}
为了工作,我相信你需要在循环中使用while
而不是if
,否则它将跳过重复的因素:
if (largest_pFact % 2 == 0) {
largest_pFact /= 2;
}
int i = 3;
int sq = Math.Sqrt((double) largest_pFact);
while (i < sq) {
while (largest_pFact % i == 0) {
largest_pFact /= i;
}
i += 2;
}
答案 3 :(得分:1)
首先,您不需要在每次迭代时运行Math.Sqrt
。
int root = Math.Sqrt((double) largest_pFact);
while (i < root)
{
if ((i % 2 != 0 | i == 2) && largest_pFact % i == 0) {
largest_pFact /= i;
root = Math.Sqrt((double) largest_pFact);
}
i++;
}
答案 4 :(得分:0)
我想:
num
/ 2 num
是否可以被素数会更快。
编辑num / 2 NOT sqrt
答案 5 :(得分:0)
在sqrt(num)和2之间查看总是比从num / 2开始更快。每个因子对(除了平方根)都有一个小于sqrt(num)的数字。
Ex:对于15,int(sqrt(15))== 3 15/3 = 5,所以你通过在3而不是7开始测试找到了“5”因子。