【问题标题】:p / primes[i] >= primes[i] logic behind thisp / primes[i] >= primes[i] 这背后的逻辑
【发布时间】:2021-10-29 06:50:27
【问题描述】:

所以从我一直关注的教程中,这是使用数组查找 3 到 100 之间的素数的代码。 第二个 for 循环中 p / primes[i] >= primes[i] 条件背后的逻辑是什么?

例如,如果我遵循 p = 5 的循环并应用条件,它将是 5 / primes[1] >= primes[1]:

因为我们知道 primes[1] = 3 这将变为 5 / 3 >= 3 立即变为假。 应该有一个测试来确保 p 的值不超过 primes[i] 的平方根 但是这里 p / primes[i] >= primes[i] 有 primes[i] 的平方根

enter code here



int primes[50] = { 0 };
int primeIndex = 2;

bool isPrime;

// hardcode prime numbers
primes[0] = 2;
primes[1] = 3;

for (p = 5; p <= 100; p = p + 2)
{
    isPrime = true;

    for (i = 1; isPrime && p / primes[i] >= primes[i]; ++i)
        if (p % primes[i] == 0)
            isPrime = false;

    if (isPrime == true)
    {
        primes[primeIndex] = p;
        ++primeIndex;
    }
}

for (i = 0;  i < primeIndex;  ++i)
     printf("%i  ", primes[i]);

printf("\n");
return 0;

}

【问题讨论】:

  • 因为素数无论如何都是正数,所以在不等式两边乘以primes[i],得到通常的检验primes[i]*primes[i] &lt;= p。请注意,您不需要测试大于 sqrt(p) 的素数来测试 p 本身是否为素数。还要注意,中止这个内循环不会中止外循环,所以你将继续使用下一个更大的 p (7, 11, ... 直到 p 达到 100)。
  • a^2 &lt;= b &lt;=&gt; a &lt;= b/a &lt;=&gt; b/a &gt;=a,谁发明了这种不可读的代码?
  • 旁注:我真的更喜欢 break 循环而不是一次又一次地检查 isPrime 变量。如果您愿意申请 goto(好吧,提前进行热烈讨论,但在我看来,这是一个有效应用程序的好例子)isPrime 变量将完全过时......
  • @Dominique a^2 &lt;= ba &lt;= b/a 相比,需要更大的整数类型(位数的两倍)来存储中间结果a^2。忽略这一点只会导致a 的大值出现错误行为,这可能很难捕获和排除故障。因此,哪个版本“不可读”是值得商榷的。
  • @nielsen:您的反应就是发明源代码 cmets 的确切原因 :-)

标签: arrays c


【解决方案1】:

逻辑是这样的:

  1. 在每对因子 (m_1, m_2) 中,m_1
  2. 如果一个数 n 有一个乘法因子 m_1,它也有一个因子 m_2 = n / m_1。所以因子实际上是成对的:m 和 n/m。
  3. 由于 (1.+2.),如果 m 是因数 n,使得 m > n/m,则 n/m 也必须是因数 n,使得 (n/m)

所以搜索“小”因素就足够了,以验证没有更大的因素。

【讨论】:

  • 我没听懂,你可以用例子详细说明
  • p / primes[i] >= primes[i] 为什么这样写而不是 p / primes[i]>= sqroot of primes[i] 类似这样
  • @rosterrz:计算一次平方根并与之比较实际上会更有效。但使用较小因子的条件也同样有效。
  • 你还可以用你上面解释的一些例子来解释一下吗?
  • @rosterrz: 如果 m > sqrt(n),则 m^2 > n,因此 m/n 必须是
【解决方案2】:

...应该有一个测试确保p的值不超过primes[i]的平方根...

没有。反之亦然:“测试以确保primes[i] 的值不超过p 的平方根”

或者:“测试以确保primes[i]的平方不超过p”。


只迭代到 √p

要只迭代到p 的根,而不是p / primes[i] &gt;= primes[i],代码可以考虑类似:

p >= sqrt(primes[i])
// or 
p >= primes[i] * primes[i]
  • sqrt(primes[i]) 引入了浮点数学。确切地说,sqrt() 没有指定,只是关闭。与整数数学相比,FP 数学也很昂贵。使用long long 时,会出现更多的舍入问题。

  • p 靠近INT_MAX 时,

    primes[i] * primes[i] 有溢出和未定义行为的风险。

  • p / primes[i] &gt;= primes[i](或者最好是primes[i] &lt;= p / primes[i])都没有问题。它的计算成本可能很低,因为一个好的编译器会看到下一个 p % primes[i] 并执行两个计算,成本大约是一个。

【讨论】:

    猜你喜欢
    • 2021-03-09
    • 2021-05-09
    • 2010-09-25
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多