确定整数位数的有效方法


144

确定C ++中一个整数中有多少个数字的一种非常有效的方法是什么?


11
在什么基础上?2?10个?
Jacob Krall

2
我想在10分制
赛斯

1
我曾经问过一个相关的问题:如何获取int的第一个数字?人们的答案中使用了许多与以下相同的方法。如果与您的任务有关,请使用以下链接[ stackoverflow.com/questions/701322/]
Dinah 2009年

内联汇编是否合格?
捷尔吉Andrasek

1
尽管所有这些答案都是以10为底的,但很容易更改以计算任何所需基数的结果。
Ira Baxter

Answers:


106

好吧,假设您知道整数的大小,最有效的方法就是查找。应该比基于较短对数的方法更快。如果您不关心计数“-”,请删除+ 1。

// generic solution
template <class T>
int numDigits(T number)
{
    int digits = 0;
    if (number < 0) digits = 1; // remove this line if '-' counts as a digit
    while (number) {
        number /= 10;
        digits++;
    }
    return digits;
}

// partial specialization optimization for 32-bit numbers
template<>
int numDigits(int32_t x)
{
    if (x == MIN_INT) return 10 + 1;
    if (x < 0) return numDigits(-x) + 1;

    if (x >= 10000) {
        if (x >= 10000000) {
            if (x >= 100000000) {
                if (x >= 1000000000)
                    return 10;
                return 9;
            }
            return 8;
        }
        if (x >= 100000) {
            if (x >= 1000000)
                return 7;
            return 6;
        }
        return 5;
    }
    if (x >= 100) {
        if (x >= 1000)
            return 4;
        return 3;
    }
    if (x >= 10)
        return 2;
    return 1;
}

// partial-specialization optimization for 8-bit numbers
template <>
int numDigits(char n)
{
    // if you have the time, replace this with a static initialization to avoid
    // the initial overhead & unnecessary branch
    static char x[256] = {0};
    if (x[0] == 0) {
        for (char c = 1; c != 0; c++)
            x[c] = numDigits((int32_t)c);
        x[0] = 1;
    }
    return x[n];
}

5
可能比我的回答快,做得好。为了提高效率,如果您知道您的输入数字将大部分为小数字(我想少于100,000),则应进行相反的测试:if(x <10)返回1;如果x = 10,则返回1。如果(x <100)返回2; 等等,以便该函数执行较少的测试并更快地退出。
squelart

29
或者,也许重新排序并嵌套if语句,以执行二进制搜索而不是线性搜索。
dave4420

1
那不是一个好主意。当体系结构扩展到256位整数时会发生什么。您需要记住回来并修改此代码。在现实生活中,这种情况不会发生,并且很可能会被用于构建正确大小的缓冲区,您现在可以通过较大的Architectres上的运行问题来面对各种缓冲区。
马丁·约克2009年

3
假设数字分布均匀,则反向线性搜索(从最大位数到1)的平均速度可能比二进制搜索快,因为带有N位的数字要比带有N-1位的图形
fa。

6
我不必担心256或128位整数。除非您需要计算宇宙中的电子数量(上次我做的是10 ^ 78个),否则64位将相当不错。32位机器持续了~~ 15年。我猜64位机器的使用寿命会更长。对于更大的数字,多精度算术会很好,并且我怀疑计算数字计数的效率是否会很重要。
Ira Baxter,2009年

74

最简单的方法是:

unsigned GetNumberOfDigits (unsigned i)
{
    return i > 0 ? (int) log10 ((double) i) + 1 : 1;
}

log10在<cmath>或中定义<math.h>。您需要对此进行概要分析,以了解它是否比此处发布的其他任何方法都要快。我不确定这对于浮点精度有多稳健。同样,该参数未签名为负值,并且log不会真正混合。


7
对于32位整数和56位浮点数,这可能有效。如果输入很长(64位),则当值接近10 ^ n的大值时,双精度日志的56位可能会导致错误的答案。预计故障会超过2 ^ 50。
伊拉·巴克斯特

1
还有一个问题是日志功能的准确性如何。我没有检查过它们在现代图书馆中的准确性,也不会盲目地相信它们在十亿分之一中表现出色。
David Thornley,2009年

@DavidThornley:日志或其他数学函数非常精确,除非在编译器命令行上指定。有些将在编译时转换为x86内在函数。有些不存在,并将扩展为现有内在函数的公式。例如,如果使用,-fpfast您会看到使用SSE内在函数而不是x87,这对IIRC精度产生的保证较少。但默认情况下没有问题。
v.oddou 2014年

@DavidThornley:不仅仅是精度。问题是,是否保证所有相关k的log10(10 ^ k)≥k。可以保证所有不可避免的舍入误差都朝着正确的方向发展。结果k + eps有效,k-eps不起作用。而且“完全精确”是幼稚的。
gnasher729

1
可以将i> 0的测试优化为i> 9
Pat

60

也许我误解了这个问题,但这不是吗?

int NumDigits(int x)  
{  
    x = abs(x);  
    return (x < 10 ? 1 :   
        (x < 100 ? 2 :   
        (x < 1000 ? 3 :   
        (x < 10000 ? 4 :   
        (x < 100000 ? 5 :   
        (x < 1000000 ? 6 :   
        (x < 10000000 ? 7 :  
        (x < 100000000 ? 8 :  
        (x < 1000000000 ? 9 :  
        10)))))))));  
}  

29
如果此解决方案最快,我也不会感到惊讶。
VisioN 2014年

32
int digits = 0; while (number != 0) { number /= 10; digits++; }

注意:“ 0”将有0位数字!如果您需要0来显示1位数字,请使用:

int digits = 0; do { number /= 10; digits++; } while (number != 0);

(感谢凯文·费根)

最后,使用探查器来了解此处所有答案中的哪个将在您的计算机上更快...


3
这可能会或可能不会比我采用的展开循环方法快-您需要分析差异(从长远来看应该可以忽略不计)。
维塔利2009年

同意,概要分析是真正确定的唯一方法!我用该评论更新了答案,因为Ben S的ceil(log10())答案已经消失了。
squelart

11

恶作剧:这是最有效的方式(中位数在编译时计算):

template <unsigned long long N, size_t base=10>
struct numberlength
{
    enum { value = 1 + numberlength<N/base, base>::value };
};

template <size_t base>
struct numberlength<0, base>
{
    enum { value = 0 };
};

在确定格式,输入元素等中数字字段所需的宽度时可能很有用。


4
首先,您的解决方案不适用于0。其次,您的解决方案不适用于变量的一般情况。第三,如果您使用常量文字,那么您已经知道它有多少位数。
维塔利

它也适用于0。它也适用于任何基础。其余的是我已经概述的有效点。
blinnov.com,2009年

3
我认为实际上并没有。它失败0,也失败于基1:),如果基为,则给出除以零的错误0。它可以修复。无论如何,我都在回顾一个很老的帖子,很抱歉,这只是我认为这不是开玩笑,实际上可能是有用的。
tjm 2010年

9

有关您接受的答案的简短版本,请参见Bit Twiddling Hacks。如果您的输入呈正态分布,则还可以通过首先检查大常量来更快地找到答案。 (v >= 1000000000)捕获了76%的值,因此检查平均起来会更快。


目前尚不清楚位纠缠实际上是否更快。即使在最坏的情况下,我修改后的方法也需要进行4次比较(如果我进一步检查分区,则可能可以将其降低到3次,尽管看起来不太可能)。我严重怀疑这会被算术运算+内存负载所击败(尽管如果访问得足够多,它们就会消失在CPU缓存中)。请记住,在他们给出的示例中,他们还将日志库2隐藏为一些抽象的IntegerLogBase2函数(其本身并不便宜)。
维塔利

就像跟进一样,如果数字是正态分布的,则是的,按顺序检查更快。但是,它的退化情况是最坏情况下速度的两倍。按位数而不是输入空间进行分区的方法意味着该行为没有简并的情况,并且始终具有最佳性能。此外,请记住,您假设数字将均匀分布。事实上,他们更有可能遵循与<ahref=" en.wikipedia.org/wiki/… > 相关的某些分布。–我的猜测是
Vitali

有点混乱的骇客并没有比上面的分区方法快,但是如果您有一个更普通的情况(例如此处的float),它们可能会很有趣。
Corwin Joy

1
给定int log2,有点混乱的黑客建议了一种获取int log10的方法。它建议了几种获取int log2的方法,主要涉及很少的比较/分支。(我认为您低估了不可预测的分支机构的成本,Vitali)。如果可以使用内联x86 asm,则BSR指令将为您提供一个值的int log2(即最高有效位的位索引)。K8(10个周期的延迟)有点慢,而Core 2(2或3个周期的延迟)快。即使在K8上,也可能比比较更快。
彼得·科德斯

在K10上,lzcnt会计数前导零,因此它几乎与bsr相同,但是输入0不再是带有不确定结果的特殊情况。等待时间:BSR:4,LZCNT:2
彼得科尔德

8

转换为字符串,然后使用内置函数

unsigned int i;
cout<< to_string(i).length()<<endl;

7
int x = 1000;
int numberOfDigits = x ? static_cast<int>(log10(abs(x))) + 1 : 1;

3
尽管就LOC而言这是有效的,但如公认的答案所述,使用log可能不会提供最佳性能。
伊恩

@Ian为什么不呢?这只是一些FPU指令。比其他答案中的所有分支和循环好得多。
的洛恩侯爵

5

以前的张贴者建议使用一个除以10的循环。由于在现代机器上进行乘法运算要快得多,因此我建议使用以下代码:

 int digits = 1, pten=10; while ( pten <= number ) { digits++; pten*=10; }

1
魔鬼在细节-说std :: numeric_limits <int> :: max ==数字会发生什么
pgast

2
如果您担心这种情况,可以添加一个额外的IF以处理非常大的值。
伊拉·巴克斯特

2
我应该观察到,在x86机器上,这种情况下使用的乘以10的常数实际上可以由编译器实现为LEA R2,[8 * R1 + R1],ADD R1,R2,因此最多需要2个时钟。变量相乘需要数十个时钟,而分频会更糟。
伊拉·巴克斯特

除法的优点是您不必担心负数。
Johannes Schaub-litb

1
我将分割方法(通过晶圆厂消除招牌问题)与基准方法进行了比较。在我的机器上,除法比乘法方法慢2倍。这是否为过早的优化实际上取决于调用的位置和方式。
Spacemoose 2014年

5

ppc体系结构具有位计数指令。这样,您可以在一条指令中确定正整数的对数基数2。例如,32位将是:

#define log_2_32_ppc(x) (31-__cntlzw(x))

如果您可以在较大的值上处理少量的误差,则可以使用另外一些说明将其转换为以10为底的对数:

#define log_10_estimate_32_ppc(x) (9-(((__cntlzw(x)*1233)+1545)>>12))

这是特定于平台的,并且稍有不准确,但是也没有分支,分割或转换为浮点的情况。一切取决于您的需求。

我只知道ppc指令,但是其他体系结构也应该有类似的指令。


此解决方案计算log2(15)= 4位和log2(9)= 4位。但是15和9需要打印不同数量的十进制数字。因此,这是行不通的,除非您不介意数字有时会用太多数字打印。但是在这种情况下,您始终可以选择“ 10”作为int的答案。
Ira Baxter,2009年

哇,大概的功能。真好
doug65536

4
 #include <iostream>
 #include <math.h>

 using namespace std;

 int main()
 {
     double num;
     int result;
     cout<<"Enter a number to find the number of digits,  not including decimal places: ";
     cin>>num;
     result = ((num<=1)? 1 : log10(num)+1);
     cout<<"Number of digits "<<result<<endl;
     return 0;
 }

这可能是解决问题的最简单方法,假设您只关心小数点前的数字,并且假设小于10的任何数字仅为1位。


1

我喜欢Ira Baxter的回答。这是一个模板变体,可处理各种大小并处理最大整数值(已更新以提升循环中的上限检查):

#include <boost/integer_traits.hpp>

template<typename T> T max_decimal()
{
    T t = 1;

    for (unsigned i = boost::integer_traits<T>::digits10; i; --i)
        t *= 10;

    return t;
}

template<typename T>
unsigned digits(T v)
{
    if (v < 0) v = -v;

    if (max_decimal<T>() <= v)
        return boost::integer_traits<T>::digits10 + 1;

    unsigned digits = 1;
    T boundary = 10;

    while (boundary <= v) {
        boundary *= 10;
        ++digits;
    }

    return digits;
}

为了从提升附加测试中获得实际的性能提升,您需要专门使用max_decimal()返回平台上每种类型的常量。一个足够魔术的编译器可以将对max_decimal()的调用优化为一个常数,但是如今大多数编译器的专业化程度更高。就目前而言,此版本可能会更慢,因为max_decimal的成本比从循环中删除的测试高。

我会将所有内容留给读者练习。


您想让上限检查首先经过单独的条件测试,这样您就不必在每次循环迭代时都进行检查。
Ira Baxter,2009年

您不想在那个温度下放10。编译器可能会考虑将t乘以与实数相乘,并使用通用乘法指令。如果您改为写“ result * = 10;” 编译器肯定会注意到乘以常数10并通过一些移位和加法来实现,这非常快。
Ira Baxter

如果乘以t的乘积始终是乘以10,则可以,编译器可以进行强度折减。但是,在这种情况下,t不是循环不变的(它只是我所拥有的整数幂函数的修改)。正确的优化是专门针对返回常量的类型。但是,您是对的,在这种情况下,该函数总是将10提高到幂,而不是将任意整数提高到幂,并且强度降低会带来很好的胜利。因此,我进行了更改...这次实际上还需要进行进一步的更改!(堆栈溢出是一个很大的浪费时间...)
2009年

1
#include <stdint.h> // uint32_t [available since C99]

/// Determine the number of digits for a 32 bit integer.
/// - Uses at most 4 comparisons.
/// - (cX) 2014 adolfo.dimare@gmail.com
/// - \see http://stackoverflow.com/questions/1489830/#27669966
/**  #d == Number length vs Number of comparisons == #c
     \code
         #d | #c   #d | #c
         ---+---   ---+---
         10 | 4     5 | 4
          9 | 4     4 | 4
          8 | 3     3 | 3
          7 | 3     2 | 3
          6 | 3     1 | 3
     \endcode
*/
unsigned NumDigits32bs(uint32_t x) {
    return // Num-># Digits->[0-9] 32->bits bs->Binary Search
    ( x >= 100000u // [6-10] [1-5]
    ?   // [6-10]
        ( x >= 10000000u // [8-10] [6-7]
        ?   // [8-10]
            ( x >= 100000000u // [9-10] [8]
            ? // [9-10]
                ( x >=  1000000000u // [10] [9]
                ?   10
                :    9
                )
            : 8
            )
        :   // [6-7]
            ( x >=  1000000u // [7] [6]
            ?   7
            :   6
            )
        )
    :   // [1-5]
        ( x >= 100u // [3-5] [1-2]
        ?   // [3-5]
            ( x >= 1000u // [4-5] [3]
            ? // [4-5]
                ( x >=  10000u // [5] [4]
                ?   5
                :   4
                )
            : 3
            )
        :   // [1-2]
            ( x >=  10u // [2] [1]
            ?   2
            :   1
            )
        )
    );
}

0

另一个代码片段与Vitali的代码片段基本相同,但是使用二进制搜索。每个无符号类型实例都会一次初始化Powers数组。有符号类型重载负责减号。

#include <limits>
#include <type_traits>
#include <array>

template <class T> 
size_t NumberOfDecPositions ( T v, typename std::enable_if<std::is_unsigned<T>::value>::type* = 0 )
{
    typedef std::array<T,std::numeric_limits<T>::digits10+1> array_type;
    static array_type powers_of_10;
    if ( powers_of_10.front() == 0 )
    {
        T n = 1;
        for ( T& i: powers_of_10 )
        {
            i = n;
            n *= 10;
        }
    }

    size_t l = 0, r = powers_of_10.size(), p;
    while ( l+1 < r )
    {
        p = (l+r)/2;
        if ( powers_of_10[p] <= v )
            l = p;
        else
            r = p;
    }
    return l + 1;
};

template <class T> 
size_t NumberOfDecPositions ( T v, typename std::enable_if<std::is_signed<T>::value>::type* = 0 )
{
    typedef typename std::make_unsigned<T>::type unsigned_type;
    if ( v < 0 )
        return NumberOfDecPositions ( static_cast<unsigned_type>(-v) ) + 1;
    else
        return NumberOfDecPositions ( static_cast<unsigned_type>(v) );
}

如果有人在乎进一步优化,请注意,powers数组的第一个元素从未使用过,l出现+1两次。


0

如果需要数字位数每个数字位置的值,请​​使用以下命令:

int64_t = number, digitValue, digits = 0;    // or "int" for 32bit

while (number != 0) {
    digitValue = number % 10;
    digits ++;
    number /= 10;
}

digit为您提供循环中当前正在处理的数字位置的值。例如,对于数字1776,数字值是:
第一循环中的
6在第二循环中的
7在第三循环
中的7在第四循环中的1


0
// Meta-program to calculate number of digits in (unsigned) 'N'.    
template <unsigned long long N, unsigned base=10>
struct numberlength
{   // http://stackoverflow.com/questions/1489830/
    enum { value = ( 1<=N && N<base ? 1 : 1+numberlength<N/base, base>::value ) };
};

template <unsigned base>
struct numberlength<0, base>
{
    enum { value = 1 };
};

{
    assert( (1 == numberlength<0,10>::value) );
}
assert( (1 == numberlength<1,10>::value) );
assert( (1 == numberlength<5,10>::value) );
assert( (1 == numberlength<9,10>::value) );

assert( (4 == numberlength<1000,10>::value) );
assert( (4 == numberlength<5000,10>::value) );
assert( (4 == numberlength<9999,10>::value) );

上面“ blinnov.com”中“实用笑话”的更正
Adolfo

0
/// Determine the number of digits for a 64 bit integer.
/// - Uses at most 5 comparisons.
/// - (cX) 2014 adolfo.dimare@gmail.com
/// - \see http://stackoverflow.com/questions/1489830/#27670035
/**  #d == Number length vs Number of comparisons == #c
     \code
         #d | #c   #d | #c     #d | #c   #d | #c
         ---+---   ---+---     ---+---   ---+---
         20 | 5    15 | 5      10 | 5     5 | 5
         19 | 5    14 | 5       9 | 5     4 | 5
         18 | 4    13 | 4       8 | 4     3 | 4
         17 | 4    12 | 4       7 | 4     2 | 4
         16 | 4    11 | 4       6 | 4     1 | 4
     \endcode
*/
unsigned NumDigits64bs(uint64_t x) {
    return // Num-># Digits->[0-9] 64->bits bs->Binary Search
    ( x >= 10000000000ul // [11-20] [1-10]
    ?
        ( x >= 1000000000000000ul // [16-20] [11-15]
        ?   // [16-20]
            ( x >= 100000000000000000ul // [18-20] [16-17]
            ?   // [18-20]
                ( x >= 1000000000000000000ul // [19-20] [18]
                ? // [19-20]
                    ( x >=  10000000000000000000ul // [20] [19]
                    ?   20
                    :   19
                    )
                : 18
                )
            :   // [16-17]
                ( x >=  10000000000000000ul // [17] [16]
                ?   17
                :   16
                )
            )
        :   // [11-15]
            ( x >= 1000000000000ul // [13-15] [11-12]
            ?   // [13-15]
                ( x >= 10000000000000ul // [14-15] [13]
                ? // [14-15]
                    ( x >=  100000000000000ul // [15] [14]
                    ?   15
                    :   14
                    )
                : 13
                )
            :   // [11-12]
                ( x >=  100000000000ul // [12] [11]
                ?   12
                :   11
                )
            )
        )
    :   // [1-10]
        ( x >= 100000ul // [6-10] [1-5]
        ?   // [6-10]
            ( x >= 10000000ul // [8-10] [6-7]
            ?   // [8-10]
                ( x >= 100000000ul // [9-10] [8]
                ? // [9-10]
                    ( x >=  1000000000ul // [10] [9]
                    ?   10
                    :    9
                    )
                : 8
                )
            :   // [6-7]
                ( x >=  1000000ul // [7] [6]
                ?   7
                :   6
                )
            )
        :   // [1-5]
            ( x >= 100ul // [3-5] [1-2]
            ?   // [3-5]
                ( x >= 1000ul // [4-5] [3]
                ? // [4-5]
                    ( x >=  10000ul // [5] [4]
                    ?   5
                    :   4
                    )
                : 3
                )
            :   // [1-2]
                ( x >=  10ul // [2] [1]
                ?   2
                :   1
                )
            )
        )
    );
}

0

对于整数“ X”,您想知道位数,可以不使用任何循环,该解决方案仅在一个公式中作用于一行,因此这是我见过的最优化的解决方案。

 int x = 1000 ; 
 cout<<numberOfDigits = 1+floor(log10(x))<<endl ; 

对于INT_MAX和负数也失败。
ranu '17

@ranu对于INT_MAX失败如何?当参数转换为double?还是指的是一些不可能的整数输入,这些整数输入使用INT_MAX十进制数字?哪一个还会使其他所有答案都失败?
的洛恩侯爵

0
int numberOfDigits(int n){

    if(n<=9){
        return 1;
    }
    return 1 + numberOfDigits(n/10);
}

这是我会做的,如果您希望以10为基数,它的运行速度非常快,而且您很可能不会获得堆栈超额购买计数整数


0
int num,dig_quant = 0;
cout<<"\n\n\t\t--Count the digits in Number--\n\n";
cout<<"Enter Number: ";
cin>>num;
for(int i = 1; i<=num; i*=10){
    if(num / i  > 0){
      dig_quant += 1;
    }
}
 cout<<"\n"<<number<<" include "<<dig_quant<<" digit"
 cout<<"\n\nGoodbye...\n\n";

0

如果更快更有效,则这是对安德烈·亚历山大德雷斯库的改进。他的版本已经比幼稚的方式快(每位数除以10)。下面的版本是恒定时间的,至少在所有大小的x86-64和ARM上都更快,但是占用的二进制代码数量是后者的两倍,因此它不是缓存友好的版本。

在facebook上的PR上此版本的基准vs alexandrescu的基准

起作用unsigned,不是signed

inline uint32_t digits10(uint64_t v) {
  return  1
        + (std::uint32_t)(v>=10)
        + (std::uint32_t)(v>=100)
        + (std::uint32_t)(v>=1000)
        + (std::uint32_t)(v>=10000)
        + (std::uint32_t)(v>=100000)
        + (std::uint32_t)(v>=1000000)
        + (std::uint32_t)(v>=10000000)
        + (std::uint32_t)(v>=100000000)
        + (std::uint32_t)(v>=1000000000)
        + (std::uint32_t)(v>=10000000000ull)
        + (std::uint32_t)(v>=100000000000ull)
        + (std::uint32_t)(v>=1000000000000ull)
        + (std::uint32_t)(v>=10000000000000ull)
        + (std::uint32_t)(v>=100000000000000ull)
        + (std::uint32_t)(v>=1000000000000000ull)
        + (std::uint32_t)(v>=10000000000000000ull)
        + (std::uint32_t)(v>=100000000000000000ull)
        + (std::uint32_t)(v>=1000000000000000000ull)
        + (std::uint32_t)(v>=10000000000000000000ull);
}

0

我正在开发一个程序,该程序需要我检查用户是否正确回答了一个数字中有多少个数字,因此我不得不开发一种方法来检查整数中的数字量。最终这是一个相对容易解决的事情。

double check=0, exponent=1000;

while(check<=1)
{
    check=number/pow(10, exponent);
    exponent--;
}

exponent=exponent+2;
cout<<exponent<<endl;

最终这是我的答案,该答案当前适用于少于10 ^ 1000个数字的数字(可以通过更改指数的值来更改)。

PS:我知道这个答案已经晚了十年,但我是2020年到达这里的,所以其他人可能会使用它。


-1
template <typename type>
class number_of_decimal_digits {   
    const powers_and_max<type> mPowersAndMax;
public:
    number_of_decimal_digits(){
    }   
    inline size_t ndigits( type i) const {
        if(i<0){
             i += (i == std::numeric_limits<type>::min());
             i=-i;
        }
        const type* begin = &*mPowersAndMax.begin();
        const type* end = begin+mPowersAndMax.size();
        return 1 + std::lower_bound(begin,end,i) - begin;
    }
    inline size_t string_ndigits(const type& i) const {
        return (i<0) + ndigits(i);
    }
    inline size_t operator[](const type& i) const {
       return string_ndigits(i);
    }
};

在那里powers_and_max,我们有(10^n)-1所有n这样

(10^n) < std::numeric_limits<type>::max()

std::numeric_limits<type>::max()在一个数组中:

template <typename type>
struct powers_and_max : protected std::vector<type>{
    typedef std::vector<type> super;
    using super::const_iterator;
    using super::size;
    type& operator[](size_t i)const{return super::operator[](i)};
    const_iterator begin()const {return super::begin();} 
    const_iterator end()const {return super::end();} 
    powers_and_max() {
       const int size = (int)(log10(double(std::numeric_limits<type>::max())));
       int j = 0;
       type i = 10;
       for( ; j<size ;++j){
           push_back(i-1);//9,99,999,9999 etc;
           i*=10;
       }
       ASSERT(back()<std::numeric_limits<type>::max());
       push_back(std::numeric_limits<type>::max());
   }
};

这是一个简单的测试:

number_of_decimal_digits<int>  ndd;
ASSERT(ndd[0]==1);
ASSERT(ndd[9]==1);
ASSERT(ndd[10]==2);
ASSERT(ndd[-10]==3);
ASSERT(ndd[-1]==2);
ASSERT(ndd[-9]==2);
ASSERT(ndd[1000000000]==10);
ASSERT(ndd[0x7fffffff]==10);
ASSERT(ndd[-1000000000]==11);
ASSERT(ndd[0x80000000]==11);

当然,可以使用有序集的任何其他实现,powers_and_max并且如果知道存在集群,但是不知道集群可能在哪里,那么自调整树实现可能是最好的


-1

有效的方法

int num;
int count = 0;
while(num)
{
   num /= 10;
   ++count;
}

#include <iostream>

int main()
{
   int num;
   std::cin >> num;

   std::cout << "number of digits for " << num << ": ";

   int count = 0;
   while(num)
   {
      num /= 10;
      ++count;
   }

   std::cout << count << '\n';

   return 0;
}

-1

首选解决方案的C ++ 11更新:

#include <limits>
#include <type_traits>
        template <typename T>
        typename std::enable_if<std::numeric_limits<T>::is_integer, unsigned int>::type
        numberDigits(T value) {
            unsigned int digits = 0;
            if (value < 0) digits = 1;
            while (value) {
                value /= 10;
                ++digits;
            }
            return digits;
        }

使用double等防止模板实例化。等


-1
int numberOfDigits(double number){
    if(number < 0){
        number*=-1;
    }
    int i=0;
        while(number > pow(10, i))
            i++;    
    cout << "This number has " << i << " digits" << endl;
    return i;
}

-2

这是我的方法:

   int digitcount(int n)
    {
        int count = 1;
        int temp = n;
        while (true)
        {
            temp /= 10;
            if (temp != 0) ++count;
            if (temp == 0) break;
        }

        return count;
    }

2
而真/休息综合征:d
ПетърПетров

-1这与六年前的第一个答案给出了相同的方法,并且没有增加任何内容(实际上,它要差得多)。

-4

这是另一种方法:

digits = sprintf(numArr, "%d", num);    // where numArr is a char array
if (num < 0)
    digits--;

这可能没有效率,只是与其他人建议的有所不同。


4
要求非常高效。相反。
Ira Baxter
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.