【问题标题】:Getting one too few divisors得到一个太少的除数
【发布时间】:2013-08-24 21:57:27
【问题描述】:

这是一个计算一个数字的除数的程序,但它给出的除数比该数字的实际除数少一个。

#include <stdio.h>

int i = 20;
int divisor;
int total;

int main()
{
    for (divisor = 1; divisor <= i; divisor++)
    {
        if ((i % divisor == 0) && (i != divisor))
        {
            total = total++;
        }
    }
    printf("%d %d\n", i, total);
    return 0;
}

数字 20 有 6 个除数,但程序说有 5 个除数。

【问题讨论】:

  • 测试i != divisor拒绝最终除数
  • 你真的不应该在这段代码中使用任何全局变量。您可以通过在具有total++ 的条件主体中添加printf("%d\n", divisor); 语句来自己调试问题。你会看到哪个除数没有打印(20),这会给你一个线索,让你知道在哪里寻找问题。

标签: c math counter division divider


【解决方案1】:
&& (i != divisor)

表示20 不会被视为除数。如果你想考虑它,放弃那段代码,你会得到整套代码,{1, 2, 4, 5, 10, 20}

即使您希望将数字计为除数,您仍然可以放弃该代码并在 for 语句中使用 &lt; 而不是 &lt;=。 p>

还有:

total = total++;

完全没有必要。它甚至可能是未定义的,我现在懒得检查,这并不重要,因为没有人长时间编写这样的代码:-)

使用任一:

total = total + 1;

或(更好):

total++;

【讨论】:

  • 每个标签都是 C,所以 total = total++; 是完全未定义的行为。 6.5 (2):“如果标量对象的副作用相对于同一标量对象的不同副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义。”
【解决方案2】:

除数计数可能比其中任何一个都更简单,而且肯定更快。需要注意的关键事实是,如果 p 是 n 的除数,那么 n/p 也是如此。只要 p 不是 n 的平方根,那么每次除法测试都会得到两个除数,而不是一个。

int divcount(int n)
{
    int i, j, count=0;
    for (i=1, j=n; i<j; j = n/++i)
    {
        if (i*j == n)
            count += 2;
    }
    if (i == j && i*j == n)
        ++count;
    return count;
}

使用 sqrt(n) 除法和 sqrt(n) 乘法即可完成工作。我之所以选择它是因为,虽然 j=n/i 和另一个 j%i 可以在大多数 CPU 上用一条除法指令完成,但我还没有看到编译器采用这种优化。由于在现代桌面处理器上乘法是单时钟的,因此 i*j == n 测试比二次除法便宜得多。

PS:如果您需要一个除数列表,它们会作为 i 和 j 值出现在循环中,并且如果 n 是一个正方形,则可能作为最后的 i==j==sqrt(n) 值。

【讨论】:

  • 谢谢,这个程序很有帮助。
【解决方案3】:

您已添加额外检查 &amp;&amp; (i != divisor),如给定答案中所述。

在这里,我使用素因数分解编写了相同的程序。这是找到大数除数的快速方法 (reference)。

// this function return the number of divisor for n.
// if n = (m^a) (n^b) ... where m, n.. are prime factors of n
// then number of divisor  d(n) = (a+1)*(b+1)..
int divisorcount(int n){

  int divider = 2;
  int limit = n/2;
  int divisorCount = 1;
  int power = 0;

  // loop through i=2...n/2
  while(divider<=limit){
    if(n%divider==0){
      // dividing numper using prime factor
      // (as smallest number devide a number 
      // is it's prime factor) and increase the
      // power term for prime factor.
     power++;
     n/=divider;
    }
    else{
      if(power != 0){
        // use the prime factor count to calculate
        // divisor count.
        divisorCount*=(power+1);
      }
      power = 0;
      divider++;
    // if n become 1 then we have completed the 
    // prime factorization of n.
    if(n==1){
      break;
    }

    }
  }
return divisorCount;
}

【讨论】:

  • 谢谢,但我收到了这个警告c:8: error: nested functions are disabled, use -fnested-functions to re-enable 这是什么意思。
  • 你应该看到这个问题:stackoverflow.com/questions/1965822/…。我使用 gcc 编译了这段代码,这段代码对我来说没有警告。
  • 可能你错过了任何函数的右括号。
  • 当我编译程序时它没有给出任何错误,但它没有给出结果它只是在我输入时停止。
  • @kylek 我检查了 n=1..100000 并且它有效并给了我结果。检查您的代码,您可能遗漏了什么。
猜你喜欢
  • 2022-11-13
  • 2020-12-31
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
  • 1970-01-01
  • 2010-09-21
  • 2021-02-07
  • 2019-09-30
相关资源
最近更新 更多