C++中不使用循环计算数字的个数

6

我需要统计一个数字中的位数。

我将数字不断除以10,直到得到0。每一次迭代都增加计数器。

int num;
cin>>num;  
while(num > 0)  
{  
  counter++;
  num = num / 10;   
}

挑战在于不使用任何循环或递归,而只用一个if语句。可能吗?

3
递归函数怎么样? - user703016
@dolan,很好的想法!我喜欢!但在这种情况下也是被禁止的 :-( - yael aviv
1
@yaelaviv log10(n)+1 其中 n 代表数字。例如,log10(1234) + 1 等于 4。 - Maroun
1
如果您不能使用递归,应在问题中声明。 - juanchopanza
@MarounMaroun,为什么要加 +1 - yael aviv
显示剩余2条评论
6个回答

13

计数器 = 对数(数值)/ 对数(10)

C++中:


#include <cmath>
....
counter = num == 0 ? 1 : log10(std::abs(num)) + 1;

你需要的是对数函数。

C++ - log10

C++ - std::abs


1
虽然对于 num == 0 仍然存在问题。 - Paul R
@Vladp,log10需要使用double变量吗? - yael aviv
2
这在 num == int min (在2s补码机器上) 的情况下不起作用。我不确定标准库std::abs在这种情况下的行为,但它给出的答案显然是错误的。[请参见http://ideone.com/exvOQK] - Mike Vine
@Mike,std::abs()继承自C的stdlib头文件,如果结果无法表示,则指定未定义行为。 - paxdiablo

3

虽然有些昂贵,但转换您的数字为字符串并获取其大小是一种简单的方法,如下面的示例:

#include <iostream>
#include <string>

int main() {
  int i = 1232323223;
  std::string str = std::to_string(std::abs(i));
  std::cout << "Number of Digits: " << str.size() <<std::endl;
}

LIVE DEMO


在2s补码机器上,不适用于int min。 - Mike Vine

3

一种方法是使用 sprintf,因为它会返回发出的字符数:

int digits(int n)
{
    char s[32];
    int len = sprintf(s, "%d", n);
    if (n < 0) len--; // NB: handle negative case
    return len;
}

我认为s应该是temp(或反之),对吗? - paxdiablo
@paxdiablo:谢谢 - 已修复。 - Paul R

3
当然可以,以下是一些示例(针对32位数字):
int numDigitsU (unsigned int n) {
    if (n <         10) return 1;
    if (n <        100) return 2;
    if (n <       1000) return 3;
    if (n <      10000) return 4;
    if (n <     100000) return 5;
    if (n <    1000000) return 6;
    if (n <   10000000) return 7;
    if (n <  100000000) return 8;
    if (n < 1000000000) return 9;
    /*      4294967295 is 2^32-1 - add more ifs as needed
       and adjust this final return as well. */
    return 10;
}

签名变量有点棘手,因为首先需要翻转符号,并且要注意 MININT 的情况。
int numDigitsS (int n) {
    if (n == MININT) n = MAXINT;  // same number of digits, usually.
    if (n < 0) n = -n;            // reverse sign.
    return numDigitsU (n);        // call the unsigned variant.
}

根据您最大的unsigned int的大小,调整最高比较值和返回值即可。

这适用于所有允许的负数编码:二进制补码、反码和原码。


哇,你比我快了10秒钟 :),+1。 - Peter
1
这里实际上是展开了循环。OK 比使用 for 循环更快,但也相当冗长。 - 101010

3

如果你考虑到 int 的最大值是有限的,其实这很容易。只需检查数字是否大于10、大于100、大于1000等等。你甚至可以进行二分查找。

int num = abs(number);
if (num < 10000)
{
    if (num < 100)
        return num < 10 ? 1:2;
    else
        return num < 1000 ? 3:4;   
}
else
{
    ...
}

你甚至可以使用二分查找。怎么做? - yael aviv
@yael 编辑:提供一个例子 - Peter

0

你可以通过以下方式找到整数的长度:

int countDigits(int *num){
    int count =0;
    while(*num>0){
        count++;
        *num /=10;
    }
    return count;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接