Подтвердить что ты не робот

Как определить количество цифр целого числа в C?

например,

n = 3432, result 4

n = 45, result 2

n = 33215, result 5

n = -357, result 3

Я думаю, я мог бы просто превратить его в строку, а затем получить длину строки, но это кажется запутанным и взломанным.

4b9b3361

Ответ 2

Рекурсивный подход: -)

int numPlaces (int n) {
    if (n < 0) return numPlaces ((n == INT_MIN) ? MAX_INT: -n);
    if (n < 10) return 1;
    return 1 + numPlaces (n / 10);
}

Или итеративный:

int numPlaces (int n) {
    int r = 1;
    if (n < 0) n = (n == INT_MIN) ? INT_MAX: -n;
    while (n > 9) {
        n /= 10;
        r++;
    }
    return r;
}

Или необработанная скорость:

int numPlaces (int n) {
    if (n < 0) n = (n == INT_MIN) ? INT_MAX : -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;
    /*      2147483647 is 2^31-1 - add more ifs as needed
       and adjust this final return as well. */
    return 10;
}

Те, что были выше, были изменены для улучшения процесса MININT. В любых странных системах, которые не следуют разумным 2 n двум правилам дополнения для целых чисел, им может потребоваться дополнительная корректировка.

Необработанная версия скорости фактически превосходит версию с плавающей запятой, измененную ниже:

int numPlaces (int n) {
    if (n == 0) return 1;
    return floor (log10 (abs (n))) + 1;
}

С сотней миллионов итераций я получаю следующие результаты:

Raw speed with 0:            0 seconds
Raw speed with 2^31-1:       1 second
Iterative with 2^31-1:       5 seconds
Recursive with 2^31-1:       6 seconds
Floating point with 1:       6 seconds
Floating point with 2^31-1:  7 seconds

Это на самом деле немного меня удивило - я думал, что чипы Intel имеют приличный FPU, но я полагаю, что общие операции FP по-прежнему не могут конкурировать с целым кодом, оптимизированным вручную.

Обновить следующие предложения stormsoul:

Тестирование многократно-итеративного решения by stormsoul дает результат 4 секунды, поэтому, хотя он намного быстрее, чем решение с разделителями-итерациями, оно все еще не соответствует оптимизированному решению if-statement.

Выбор аргументов из пула из 1000 произвольно сгенерированных чисел подтолкнул время сырой скорости до 2 секунд, поэтому, хотя оно появляется, возможно, было некоторое преимущество иметь один и тот же аргумент каждый раз, но он все же является самым быстрым подходом.

Компиляция с -O2 улучшала скорость, но не относительные позиции (я увеличил количество итераций в десять раз, чтобы проверить это).

Любой дальнейший анализ должен серьезно заняться внутренней работой эффективности ЦП (различные типы оптимизации, использование кэшей, предсказание ветвей, какой у вас на самом деле есть процессор, температура окружающей среды в помещении и т.д.), которые будет мешать моей оплачиваемой работе:-). Это было интересное развлечение, но в какой-то момент отдача от инвестиций для оптимизации становится слишком мала, чтобы иметь значение. Я думаю, что у нас есть достаточно решений, чтобы ответить на вопрос (который был, в конце концов, не о скорости).

Дальнейшее обновление:

Это будет мое последнее обновление этого ответа, запрещающее вопиющие ошибки, не зависящие от архитектуры. Вдохновленный бурными мерными мерками, я отправляю свою тестовую программу (модифицированную согласно собственной тестовой программе), а также некоторые примеры для всех методов, показанных в ответах здесь. Имейте в виду, что это на конкретной машине, ваш пробег может варьироваться в зависимости от того, где вы его запускаете (именно поэтому я отправляю тестовый код).

Сделайте с этим, как хотите:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <time.h>

#define numof(a) (sizeof(a) / sizeof(a[0]))

/* Random numbers and accuracy checks. */

static int rndnum[10000];
static int rt[numof(rndnum)];

/* All digit counting functions here. */

static int count_recur (int n) {
    if (n < 0) return count_recur ((n == INT_MIN) ? INT_MAX : -n);
    if (n < 10) return 1;
    return 1 + count_recur (n / 10);
}

static int count_diviter (int n) {
    int r = 1;
    if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
    while (n > 9) {
        n /= 10;
        r++;
    }
    return r;
}

static int count_multiter (int n) {
    unsigned int num = abs(n);
    unsigned int x, i;
    for (x=10, i=1; ; x*=10, i++) {
        if (num < x)
            return i;
        if (x > INT_MAX/10)
            return i+1;
    }
}

static int count_ifs (int n) {
    if (n < 0) n = (n == INT_MIN) ? INT_MAX : -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;
    /*      2147483647 is 2^31-1 - add more ifs as needed
    and adjust this final return as well. */
    return 10;
}

static int count_revifs (int n) {
    if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
    if (n > 999999999) return 10;
    if (n > 99999999) return 9;
    if (n > 9999999) return 8;
    if (n > 999999) return 7;
    if (n > 99999) return 6;
    if (n > 9999) return 5;
    if (n > 999) return 4;
    if (n > 99) return 3;
    if (n > 9) return 2;
    return 1;
}

static int count_log10 (int n) {
    if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
    if (n == 0) return 1;
    return floor (log10 (n)) + 1;
}

static int count_bchop (int n) {
    int r = 1;
    if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
    if (n >= 100000000) {
        r += 8;
        n /= 100000000;
    }
    if (n >= 10000) {
        r += 4;
        n /= 10000;
    }
    if (n >= 100) {
        r += 2;
        n /= 100;
    }
    if (n >= 10)
        r++;

    return r;
}

/* Structure to control calling of functions. */

typedef struct {
    int (*fnptr)(int);
    char *desc;
} tFn;

static tFn fn[] = {
    NULL,                              NULL,
    count_recur,    "            recursive",
    count_diviter,  "     divide-iterative",
    count_multiter, "   multiply-iterative",
    count_ifs,      "        if-statements",
    count_revifs,   "reverse-if-statements",
    count_log10,    "               log-10",
    count_bchop,    "          binary chop",
};
static clock_t clk[numof (fn)];

int main (int c, char *v[]) {
    int i, j, k, r;
    int s = 1;

    /* Test code:
        printf ("%11d %d\n", INT_MIN, count_recur(INT_MIN));
        for (i = -1000000000; i != 0; i /= 10)
            printf ("%11d %d\n", i, count_recur(i));
        printf ("%11d %d\n", 0, count_recur(0));
        for (i = 1; i != 1000000000; i *= 10)
            printf ("%11d %d\n", i, count_recur(i));
        printf ("%11d %d\n", 1000000000, count_recur(1000000000));
        printf ("%11d %d\n", INT_MAX, count_recur(INT_MAX));
    /* */

    /* Randomize and create random pool of numbers. */

    srand (time (NULL));
    for (j = 0; j < numof (rndnum); j++) {
        rndnum[j] = s * rand();
        s = -s;
    }
    rndnum[0] = INT_MAX;
    rndnum[1] = INT_MIN;

    /* For testing. */
    for (k = 0; k < numof (rndnum); k++) {
        rt[k] = (fn[1].fnptr)(rndnum[k]);
    }

    /* Test each of the functions in turn. */

    clk[0] = clock();
    for (i = 1; i < numof (fn); i++) {
        for (j = 0; j < 10000; j++) {
            for (k = 0; k < numof (rndnum); k++) {
                r = (fn[i].fnptr)(rndnum[k]);
                /* Test code:
                    if (r != rt[k]) {
                        printf ("Mismatch error [%s] %d %d %d %d\n",
                            fn[i].desc, k, rndnum[k], rt[k], r);
                        return 1;
                    }
                /* */
            }
        }
        clk[i] = clock();
    }

    /* Print out results. */

    for (i = 1; i < numof (fn); i++) {
        printf ("Time for %s: %10d\n", fn[i].desc, (int)(clk[i] - clk[i-1]));
    }

    return 0;
}

Помните, что вам нужно убедиться, что вы используете правильную командную строку для ее компиляции. В частности, вам может потребоваться явно указать математическую библиотеку для работы log10(). Командная строка, которую я использовал в Debian, была gcc -o testprog testprog.c -lm.

И, с точки зрения результатов, вот панель лидеров для моей среды:

Уровень оптимизации 0:

Time for reverse-if-statements:       1704
Time for         if-statements:       2296
Time for           binary chop:       2515
Time for    multiply-iterative:       5141
Time for      divide-iterative:       7375
Time for             recursive:      10469
Time for                log-10:      26953

Уровень оптимизации 3:

Time for         if-statements:       1047
Time for           binary chop:       1156
Time for reverse-if-statements:       1500
Time for    multiply-iterative:       2937
Time for      divide-iterative:       5391
Time for             recursive:       8875
Time for                log-10:      25438

Ответ 3

Псевдо-алгоритм двоичного поиска не получает цифр из r в v.

if (v < 0 ) v=-v;

r=1;

if (v >= 100000000)
{
  r+=8;
  v/=100000000;
}

if (v >= 10000) {
    r+=4;
    v/=10000;
}

if (v >= 100) {
    r+=2;
    v/=100;
}

if( v>=10)
{
    r+=1;
}

return r;

Ответ 4

Самый короткий ответ: snprintf(0,0,"%+d",n)-1

Ответ 5

Разделите на 10 в цикле, пока результат не достигнет нуля. Число итераций будет соответствовать числу десятичных цифр.

Предполагая, что вы ожидаете получить 0 цифр в нулевом значении:

int countDigits( int value )
{
    int result = 0;
    while( value != 0 ) {
       value /= 10;
       result++;
    }
    return result;
}

Ответ 6

Вы можете сделать: floor (log10 (abs (x))) + 1 Или, если вы хотите экономить на циклах, вы могли бы просто делать сравнения

if(x<10)
  return 1;
if(x<100)
  return 2;
if(x<1000)
  return 3;
etc etc

Это позволяет избежать любых дорогостоящих вычислительных функций, таких как журнал или даже умножение или деление. Хотя это неэлегантно, это можно скрыть, инкапсулируя его в функцию. Это не сложно или сложно поддерживать, поэтому я бы не отказался от этого подхода из-за плохой практики кодирования; Я чувствую, что это сделает бросок ребенка водой для ванны.

Ответ 7

Версия с постоянной стоимостью, использующая сборку x86 и таблицу поиска:

int count_bsr(int i) {
    struct {
            int max;
            int count;
    } static digits[32] = {
            { 9, 1 }, { 9, 1 }, { 9, 1 }, { 9, 1 },
            { 99, 2 }, { 99, 2 }, { 99, 2 },
            { 999, 3 }, { 999, 3 }, { 999, 3 },
            { 9999, 4 }, { 9999, 4 }, { 9999, 4 }, { 9999, 4 },
            { 99999, 5 }, { 99999, 5 }, { 99999, 5 },
            { 999999, 6 }, { 999999, 6 }, { 999999, 6 },
            { 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 },
            { 99999999, 8 }, { 99999999, 8 }, { 99999999, 8 },
            { 999999999, 9 }, { 999999999, 9 }, { 999999999, 9 },
            { INT_MAX, 10 }, { INT_MAX, 10 }
    };
        register const int z = 0;
        register unsigned log2;
        if (i < 0) i = -i;
        __asm__ __volatile__ (
                "bsr %1, %0;"  \
                "cmovz %2, %0;"\
                : "=r" (log2)  \
                : "rm" (i), "r"(z));
        return digits[log2].count + ( i > digits[log2].max );
}

Другой, с меньшей таблицей поиска и приближением log10, взятым из здесь.

int count_bsr2( int i ) {
    static const unsigned limits[] =
            {0, 10, 100, 1000, 10000, 100000,
             1000000, 10000000, 100000000, 1000000000};
        register const int z = 0;
        register int l, log2;
        if (i < 0) i = -i;
        __asm__ __volatile__ (
                "bsr %1, %0;"  \
                "cmovz %2, %0;"\
                : "=r" (log2)  \
                : "rm" (i), "r"(z));
       l = (log2 + 1) * 1233 >> 12;
       return (l + ((unsigned)i >= limits[l]));
}

Оба из них используют тот факт, что на x86 -INT_MIN равен INT_MIN.

Update:

В соответствии с предложением здесь приведены тайминги для count_bsr и несколько более быстрых 64-битных подпрограмм count_bsr_mod по сравнению с бинарным поиском и бинарными алгоритмами с использованием очень приятной программы тестирования paxdiablo, модифицированной для генерации множеств со случайным распределением знака. Тесты были построены с использованием gcc 4.9.2 с использованием опций "-O3 -falign-functions = 16 -falign-jumps = 16 -march = corei7-avx" и выполнялись в спокойной системе Sandy Bridge с выключенным турбо- и спящим режимами.

Time for               bsr mod:     270000  
Time for                   bsr:     340000  
Time for           binary chop:     800000  
Time for         binary search:     770000  
Time for     binary search mod:     470000  

Источник для теста,

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <time.h>

#define numof(a) (sizeof(a) / sizeof(a[0]))

/* Random numbers and accuracy checks. */

static int rndnum[10000];
static int rt[numof(rndnum)];

/* All digit counting functions here. */

static int count_bchop (int n) {
    int r = 1;
    if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
    if (n >= 100000000) {
        r += 8;
        n /= 100000000;
    }
    if (n >= 10000) {
        r += 4;
        n /= 10000;
    }
    if (n >= 100) {
        r += 2;
        n /= 100;
    }
    if (n >= 10)
        r++;

    return r;
}

static int count_bsearch(int i)
{
    if (i < 0)
    {
        if (i == INT_MIN)
            return 11; // special case for -2^31 because 2^31 can't fit in a two complement 32-bit integer
        i = -i;
    }
    if              (i < 100000) {
        if          (i < 1000) {
            if      (i < 10)         return 1;
            else if (i < 100)        return 2;
            else                     return 3;
        } else {
            if      (i < 10000)      return 4;
            else                     return 5;
        }
    } else {
        if          (i < 10000000) {
            if      (i < 1000000)    return 6;
            else                     return 7;
        } else {
            if      (i < 100000000)  return 8;
            else if (i < 1000000000) return 9;
            else                     return 10;
        }
    }
}

// Integer log base 10, modified binary search.
static int count_bsearch_mod(int i) {
   unsigned x = (i >= 0) ? i : -i;
   if (x > 99)
      if (x > 999999)
         if (x > 99999999)
            return 9 + (x > 999999999);
         else
            return 7 + (x > 9999999);
      else
         if (x > 9999)
            return 5 + (x > 99999);
         else
            return 3 + (x > 999);
   else
         return 1 + (x > 9);
}

static int count_bsr_mod(int i) {
    struct {
            int m_count;
            int m_threshold;
    } static digits[32] =
    {
      { 1, 9 }, { 1, 9 }, { 1, 9 }, { 1, 9 },
      { 2, 99 }, { 2, 99 }, { 2, 99 },
      { 3, 999 }, { 3, 999 }, { 3, 999 },
      { 4, 9999 }, { 4, 9999 }, { 4, 9999 }, { 4, 9999 },
      { 5, 99999 }, { 5, 99999 }, { 5, 99999 },
      { 6, 999999 }, { 6, 999999 }, { 6, 999999 },
      { 7, 9999999 }, { 7, 9999999 }, { 7, 9999999 }, { 7, 9999999 },
      { 8, 99999999 }, { 8, 99999999 }, { 8, 99999999 },
      { 9, 999999999 }, { 9, 999999999 }, { 9, 999999999 },
      { 10, INT_MAX }, { 10, INT_MAX }
    };
        __asm__ __volatile__ (
            "cdq                    \n\t"
            "xorl %%edx, %0         \n\t"
            "subl %%edx, %0         \n\t"
            "movl %0, %%edx         \n\t"
            "bsrl %0, %0            \n\t"
            "shlq $32, %%rdx        \n\t"
            "movq %P1(,%q0,8), %q0  \n\t"
            "cmpq %q0, %%rdx        \n\t"
            "setg %%dl              \n\t"
            "addl %%edx, %0         \n\t"
                : "+a"(i)
                : "i"(digits)
                : "rdx", "cc"
        );
    return i;
}

static int count_bsr(int i) {
    struct {
            int max;
            int count;
    } static digits[32] = {
            { 9, 1 }, { 9, 1 }, { 9, 1 }, { 9, 1 },
            { 99, 2 }, { 99, 2 }, { 99, 2 },
            { 999, 3 }, { 999, 3 }, { 999, 3 },
            { 9999, 4 }, { 9999, 4 }, { 9999, 4 }, { 9999, 4 },
            { 99999, 5 }, { 99999, 5 }, { 99999, 5 },
            { 999999, 6 }, { 999999, 6 }, { 999999, 6 },
            { 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 },
            { 99999999, 8 }, { 99999999, 8 }, { 99999999, 8 },
            { 999999999, 9 }, { 999999999, 9 }, { 999999999, 9 },
            { INT_MAX, 10 }, { INT_MAX, 10 }
    };
        register const int z = 0;
        register unsigned log2;
        if (i < 0) i = -i;
        __asm__ __volatile__ (
                "bsr %1, %0;"  \
                "cmovz %2, %0;"\
                : "=r" (log2)  \
                : "rm" (i), "r"(z));
        return digits[log2].count + ( i > digits[log2].max );
}

/* Structure to control calling of functions. */

typedef struct {
    int (*fnptr)(int);
    const char *desc;
} tFn;

static tFn fn[] = {
 {   NULL,                              NULL },
 {   count_bsr_mod,  "              bsr mod" },
 {   count_bsr,      "                  bsr" },
 {   count_bchop,    "          binary chop" },
 {   count_bsearch,  "        binary search" },
 {   count_bsearch_mod,"    binary search mod"}
};
static clock_t clk[numof (fn)];

int main (int c, char *v[]) {
    int i, j, k, r;
    int s = 1;

    /* Test code:
        printf ("%11d %d\n", INT_MIN, count_bsearch(INT_MIN));
        //for (i = -1000000000; i != 0; i /= 10)
        for (i = -999999999; i != 0; i /= 10)
            printf ("%11d %d\n", i, count_bsearch(i));
        printf ("%11d %d\n", 0, count_bsearch(0));
        for (i = 1; i != 1000000000; i *= 10)
            printf ("%11d %d\n", i, count_bsearch(i));
        printf ("%11d %d\n", 1000000000, count_bsearch(1000000000));
        printf ("%11d %d\n", INT_MAX, count_bsearch(INT_MAX));
    return 0;
    /* */

    /* Randomize and create random pool of numbers. */

    int p, n;
    p = n = 0;
    srand (time (NULL));
    for (j = 0; j < numof (rndnum); j++) {
        rndnum[j] = ((rand() & 2) - 1) * rand();
    }
    rndnum[0] = INT_MAX;
    rndnum[1] = INT_MIN;

    /* For testing. */
    for (k = 0; k < numof (rndnum); k++) {
        rt[k] = (fn[1].fnptr)(rndnum[k]);
    }

    /* Test each of the functions in turn. */

    clk[0] = clock();
    for (i = 1; i < numof (fn); i++) {
        for (j = 0; j < 10000; j++) {
            for (k = 0; k < numof (rndnum); k++) {
                r = (fn[i].fnptr)(rndnum[k]);
                /* Test code:
                    if (r != rt[k]) {
                        printf ("Mismatch error [%s] %d %d %d %d\n",
                            fn[i].desc, k, rndnum[k], rt[k], r);
                        return 1;
                    }
                /* */
            }
        }
        clk[i] = clock();
    }

    /* Print out results. */

    for (i = 1; i < numof (fn); i++) {
        printf ("Time for %s: %10d\n", fn[i].desc, (int)(clk[i] - clk[i-1]));
    }

    return 0;
}

Ответ 9

Вот развернутый двоичный поиск без какого-либо деления или умножения. В зависимости от распределения присвоенных ему чисел он может или не может бить других, выполняемых с помощью развернутых операторов if, но всегда должен бить те, которые используют циклы и умножение/деление/log10.

При равномерном распределении случайных чисел, охватывающих весь диапазон, на моей машине он составлял в среднем 79% времени выполнения paxdiablo count_bchop(), 88% - времени count_ifs() и 97% времени count_revifs ().

С экспоненциальным распределением (вероятность числа, содержащего n цифр, равна таковой из него, которая имеет m цифр, где m ≠ n) count_ifs() и count_revifs() оба били мою функцию. Я не уверен, почему на этом этапе.

int count_bsearch(int i)
{
    if (i < 0)
    {
        if (i == INT_MIN)
            return 11; // special case for -2^31 because 2^31 can't fit in a two complement 32-bit integer
        i = -i;
    }
    if              (i < 100000) {
        if          (i < 1000) {
            if      (i < 10)         return 1;
            else if (i < 100)        return 2;
            else                     return 3;
        } else {
            if      (i < 10000)      return 4;
            else                     return 5;
        }
    } else {
        if          (i < 10000000) {
            if      (i < 1000000)    return 6;
            else                     return 7;
        } else {
            if      (i < 100000000)  return 8;
            else if (i < 1000000000) return 9;
            else                     return 10;
        }
    }
}

Ответ 10

Я наткнулся на это во время поиска в google: http://www.hackersdelight.org/hdcodetxt/ilog.c.txt

Быстрый тест показал, что выигрывают бинарные поисковые методы. код lakshmanaraj довольно хорош, Александр Коробка на 30% быстрее, Deadcode's немного быстрее (~ 10%), но я обнаружил, что следующие трюки из вышеупомянутой ссылки дают еще 10% улучшения.

// Integer log base 10, modified binary search.
int ilog10c(unsigned x) {
   if (x > 99)
      if (x < 1000000)
         if (x < 10000)
            return 3 + ((int)(x - 1000) >> 31);
         // return 3 - ((x - 1000) >> 31);              // Alternative.
         // return 2 + ((999 - x) >> 31);               // Alternative.
         // return 2 + ((x + 2147482648) >> 31);        // Alternative.
         else
            return 5 + ((int)(x - 100000) >> 31);
      else
         if (x < 100000000)
            return 7 + ((int)(x - 10000000) >> 31);
         else
            return 9 + ((int)((x-1000000000)&~x) >> 31);
         // return 8 + (((x + 1147483648) | x) >> 31);  // Alternative.
   else
      if (x > 9)
            return 1;
      else
            return ((int)(x - 1) >> 31);
         // return ((int)(x - 1) >> 31) | ((unsigned)(9 - x) >> 31);  // Alt.
         // return (x > 9) + (x > 0) - 1;                             // Alt.
}

Обратите внимание, что это журнал 10, а не число цифр, поэтому digits = ilog10c(x)+1.

Не поддерживает негативы, но это легко фиксируется с помощью -.

Ответ 11

    int n = 437788;
    int N = 1; 
    while (n /= 10) N++; 

Ответ 12

if (x == MININT) return 10;  //  abs(MININT) is not defined
x = abs (x);
if (x<10) return 1;
if (x<100) return 2;
if (x<1000) return 3;
if (x<10000) return 4;
if (x<100000) return 5;
if (x<1000000) return 6;
if (x<10000000) return 7;
if (x<100000000) return 8;
if (x<1000000000) return 9;
return 10; //max len for 32-bit integers

Очень неэлегантный. Но быстрее, чем все другие решения. Целевое подразделение и журналы FP являются дорогостоящими. Если производительность не является проблемой, решение log10 является моим любимым.

Ответ 13

Немного подстройте язык C:

floor( log10( abs( (number)?number:1 ) ) + 1 );

Ответ 14

НЕ используйте пол (log10 (...)). Это функции с плавающей запятой и медленные, чтобы добавить. Я считаю, что самым быстрым способом была бы эта функция:

int ilog10(int num)
{
   unsigned int num = abs(num);
   unsigned int x, i;
   for(x=10, i=1; ; x*=10, i++)
   {
      if(num < x)
         return i;
      if(x > INT_MAX/10)
         return i+1;
   }
}

Обратите внимание, что версия бинарного поиска, предложенная некоторыми людьми, может быть медленнее из-за неверных предсказаний отрасли.

EDIT:

Я провел некоторое тестирование и получил некоторые действительно интересные результаты. Я назначил свою функцию вместе со всеми функциями, проверенными Pax, и функцией двоичного поиска, заданной lakshmanaraj. Тестирование выполняется с помощью следующего фрагмента кода:

start = clock();
for(int i=0; i<10000; i++)
   for(int j=0; j<10000; j++)
      tested_func(numbers[j]);
end = clock();
tested_func_times[pass] = end-start;

Где массив numbers [] содержит случайно сгенерированные числа во всем диапазоне типа int (запрет MIN_INT). Тестирование повторялось для каждой тестируемой функции в массиве SAME numbers []. Весь тест проводился 10 раз, результаты были усреднены по всем проходам. Код был скомпилирован с GCC 4.3.2 с уровнем оптимизации -O3.

Вот результаты:

floating-point log10:     10340ms
recursive divide:         3391ms
iterative divide:         2289ms
iterative multiplication: 1071ms
unrolled tests:           859ms
binary search:            539ms

Я должен сказать, что я очень удивился. Бинарный поиск выполнялся намного лучше, чем я думал. Я проверил, как GCC скомпилировал этот код в asm. О_О. Теперь это впечатляет. Он был оптимизирован намного лучше, чем я думал, возможно, избегая большинства отраслей по-настоящему умным образом. Неудивительно, что это БЫСТРО.

Ответ 15

вы можете найти число цифр в числе, используя эту формулу ceil (log10 (abs (x))), где ceil возвращает целое число, большее числа

Ответ 16

Я думаю, самый простой способ:

 int digits = 0;
if (number < 0) digits = 1;
while (number) {
    number /= 10;
    digits++;
}

цифры дает ответ.

Ответ 17

Простой способ найти длину (например, число цифр) целого числа со знаком:

while ( abs(n) > 9 )
{
    num /= 10;
    ++len;
}

Где n - это целое число, в котором вы хотите найти длину и где len равно числу цифр в целых числах. Это работает для обоих значений n (отрицательный или положительный).

Вызов abs() не является обязательным, если вы работаете только с положительными целыми числами.

Ответ 18

void main()
{     
    int a,i;
    printf("Enter the number :");       
    scanf("%d",&a);

    while(a>0)     
    {
        a=a/10;   
        i++;  
    }

    getch();
}