Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何求解素数函数的大O表示法?_C#_Algorithm_Big O - Fatal编程技术网

C# 如何求解素数函数的大O表示法?

C# 如何求解素数函数的大O表示法?,c#,algorithm,big-o,C#,Algorithm,Big O,我正在努力理解大O符号。很抱歉,如果我问了一些太明显的问题,但我似乎无法理解这一点 我有下面的C#代码函数,我正试图为它计算Big-O符号 for (i = 2; i < 100; i++) { for (j = 2; j <= (i / j); j++) if ((i % j) == 0) break; // if factor found, not prime if (j > (i / j))

我正在努力理解大O符号。很抱歉,如果我问了一些太明显的问题,但我似乎无法理解这一点

我有下面的C#代码函数,我正试图为它计算Big-O符号

for (i = 2; i < 100; i++)
     {
        for (j = 2; j <= (i / j); j++)
           if ((i % j) == 0) break; // if factor found, not prime
        if (j > (i / j)) 
           Console.WriteLine("{0} is prime", i);
     }
因为它是一个线性函数,所以它是O(n)和一个嵌套循环,不依赖于周围循环中的变量

for(i = 0; i < 100; i++)
    for(j = 0; j < 100; j++)
(i=0;i<100;i++)的

对于(j=0;j<100;j++)
是O(n^2)?但是我如何计算一个函数,比如上面的函数,其中第二个循环依赖于第一个循环,并创建一个非线性函数

我找到了线性数学的一个定义

线性算法可扩展到大型问题。每当N翻倍, 运行时间增加了一倍(但不多)


虽然这似乎是对这个代码段如何运行的一个很好的描述,但这是否意味着它是O(N Log[N]),如果是,我该如何计算呢?

@Jon很接近,但他的分析有点错误,并且算法的真正复杂性是
O(N*sqrt(N))

这是基于这样一个事实,即对于每个编号
i
,您应该在内部循环中执行的预期“工作”数量为:

1/2 + 2/3 + 3/4 + ... + (sqrt(i)-1)/sqrt(i) = 
 = 1-1/2 + 1-1/3 + ... + 1-1/sqrt(i)
 = sqrt(i) - (1/2 + 1/3 + ... + 1/sqrt(i)
 = sqrt(i) - H_sqrt(i)
由于
H_sqrt(i)
()是在
O(log(sqrt(i))=O(1/2*log(i)
中,我们可以得出这样的结论:对于每个素数计算,复杂性是
O(sqrt(i)-log(i))=O(sqrt(i))

由于这是每个
i
重复进行的,因此问题的总复杂性是
O(sqrt(2)+sqrt(3)+…+sqrt(n))
。根据,平方根的和是
O(n*sqrt(n))
,比
O(nlogn)
更“糟糕”

注意事项:

  • 第一个总和等于sqrt(i),因为这是
    j>(i/j)
    的点
  • 对于每个
    j
    ,第一个和是
    (j-1)/j
    ,因为平均每
    j
    个元素中有一个进入了中断状态(1/3的元素可以除以3,1/4除以4,…),这就剩下了我们没有的
    (j-1)/j
    ,这是我们所期望的工作
  • 任何常数
    k
    的等式
    O(log(sqrt(n))=O(1/2*log(n)
    来自
    O(log(n^k))=O(k*log(n))=O(log(n))
    (在您的例子中,k=1/2)

  • 通过分析您的算法,我得出以下结论:

    • i
      处于区间
      [2,3]
      时,内部循环不会迭代
    • i
      处于区间
      [4,8]
      时,内部循环会迭代一次
    • i
      处于区间
      [9,15]
      时,内部循环会迭代两次
    • i
      处于区间
      [16,24]
      时,内部循环会迭代三次
    • i
      处于区间
      [25,35]
      时,内部循环会迭代四次
    • i
      在区间
      [36,48]
      中时,内部循环会迭代五次
    • i
      在区间
      [49,63]
      中时,内部循环会迭代六次
    • i
      [64,80]
      间隔内时,内部循环会迭代七次
    • i
      [81,99]
      间隔内时,内部循环会迭代八次。 我必须去一个大于100的范围来验证上述内容
    • i
      [100120]
      间隔内时,内部循环会迭代九次
    取决于
    i的
    值的间隔可以如下表示:

    [i^2, i * (i + 2)]
    
    因此,我们可以这样做:

    经验验证:

    通过一个有用的WolframAlpha链接:

    http://www.wolframalpha.com/input/?i=sum[+floor%28+i^%281%2F2%29%29+-+1+]+with+i+from+2+to+99.
    
    我们可以正式声明如下:


    我查看了您的代码-没有n。代码不依赖于任何n。它将始终在完全相同的固定时间内运行。您可以计算它需要多长时间,但它始终是相同的常量时间。如前所述,以“for(I=2;I<100;++I)”开头的代码在O(1)中运行

    因此,将第一行更改为

    for (i = 2; i < n; ++i)
    
    (i=2;i 现在我们有了实际上依赖于n的代码。内部循环最多运行sqrt(i)次迭代,比sqrt(n)次要少。外部循环大约运行n次迭代。所以执行时间最多为O(n sqrt(n))=O(n^1.5)

    实际上,它会运行得更快。它通常不会运行到sqrt(i),但只有在找到i的除数之前才会运行。一半的数字可以被2整除(一次迭代)。剩下的三分之一可以被3整除(两次迭代)。剩下的五分之一可以被5整除(四次迭代)。大约n/ln n个数字是带有sqrt(n)的素数迭代次数。大约n/ln更多的数字是两个素数>n^(1/3)与最多sqrt(n)次迭代的乘积。其余的少于n^(1/3)次迭代

    所以代码实际上是在O(n^1.5/ln n)中运行的。您可以通过使用一个素数表来改进这一点,直到sqrt(n),然后将其减少到O(n^1.5/ln^2 n)


    但是在实践中,你可以打赌Console.WriteLine()比检查一个数字是否为素数花费的时间要长得多。如果你坚持列出所有素数,那么你的算法将被O(n/ln)控制用一个非常大的常数因子来显示结果,直到n变得非常大。

    次要问题-你是如何得到那张图的?仅供参考,我认为这个问题更适合。该网站是为更多的理论编程问题而设计的,而StackOverflow是为解决编程问题而设计的。与任何网站一样,请确保阅读发帖指南,熟悉需要回答的问题。@JLRishe-请不要添加这样的评论。如果您认为该问题应该
    for (i = 2; i < n; ++i)