计算一个数字中的位数 - 这两个解决方案中的哪一个更快?

时间:2014-02-17 19:34:04

标签: algorithm execution-time

最近我在接受采访时被问到如何编写算法来计算给定数字中的位数。因此,例如,如果给我一个数字500,结果将是3.如果给我一个数字15345,结果将是5.

我想出了两个可能的解决方案:

  1. 递归地将数字除以10,直到结果小于1,然后返回我所做的递归计数。

  2. 将数字转换为字符串,然后计算此字符串中元素的数量。

  3. 然后我被问到在处理非常大的数字时哪个操作更有效,我无法给出一个好的答案。所以我的问题是这里的正确答案是什么 - 哪种算法更快,为什么?

4 个答案:

答案 0 :(得分:1)

好吧,要将整数转换为字符串,基本itoa(整数到字符串)函数的工作方式如下:

result = ""
while (number > 0)
{
    digit = number % 10
    append digit to result
    number = number / 10
}

因此,您的第一个和第二个解决方案之间没有太大区别。第一个解决方案将采用 O(n)迭代,其中 n 是整数中的位数。第二种解决方案具有相同的复杂性,另外计算 O(n)时间内字符串中的 n 位数,总计 O(2n) = O(n)复杂性。

其他算法也是可能的。例如,您可以查看设置的最高位,并将其与值表进行匹配。

答案 1 :(得分:1)

我计时了三个变种:

  • 重复分裂
  • 对数
  • 字符串长度

长度为10的倍数。我每次运行10000次。

以微秒为单位的结果:

length     division     logarithm     string length
---------------------------------------------------
  10           7           10            16
  20          14           14            26
  30          28           14            41
  40          46           14            59
  50          73           14            80
  60          91           14            80
  70         113           14            98
  80         136           14           106
  90         170           14           116
 100         197           14           129

这些数据中有各种来源的文物,但我认为你明白这一点。

答案 2 :(得分:0)

这在很大程度上取决于数字的给定方式。我会解释你给了一个存储为机器整数的数字。在那种情况下,我认为最重要的是采用数字的对数,这应该在不变的时间给出答案。

你的答案都是以线性时间运行的,所以应该考虑它们 等效。

答案 3 :(得分:0)

只是为了记录,这是最快的方法,假设输入是无符号长整数或某种类型的int:

int count_digits( unsigned long n ){
   unsigned long long quotient;
   unsigned int ctDigits = 1;
   while( n > 9 ){
      ctDigits++;
      quotient = (n >> 1) + (n >> 2);
      quotient += (quotient >> 4);   
      quotient += (quotient >> 8);   
      quotient += (quotient >> 16);   
      quotient = quotient >> 3;   
      n -= ((quotient << 2) + quotient) << 1; // computes the remainder
   }
   return ctDigits;
}

任何使用除法(包括任何itoa /字符串转换)的解决方案都会慢得多,因为除法是一项昂贵的操作。在高速计算领域,分工是坏事,坏事。