webentwicklung-frage-antwort-db.com.de

Wie bestimme ich die Anzahl der Stellen einer ganzen Zahl in C?

zum Beispiel,

n = 3432, result 4

n = 45, result 2

n = 33215, result 5

n = -357, result 3

Ich denke, ich könnte es einfach in einen String umwandeln und dann die Länge des Strings bekommen, aber das scheint gewunden und hacky zu sein.

63
willc2
floor (log10 (abs (x))) + 1

http://en.wikipedia.org/wiki/Logarithm

95
eduffy

Der rekursive Ansatz :-)

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);
}

Oder iterativ:

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;
}

Oder rohe Geschwindigkeit:

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;
}

Die oben genannten wurden modifiziert, um MININT besser zu verarbeiten. Auf allen seltsamen Systemen, die nicht sinnvoll folgen 2n Wenn zwei Regeln für ganze Zahlen ergänzen, müssen sie möglicherweise weiter angepasst werden.

Die Rohgeschwindigkeitsversion übertrifft tatsächlich die unten modifizierte Gleitkommaversion:

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

Mit hundert Millionen Iterationen erhalte ich die folgenden Ergebnisse:

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

Das hat mich ein wenig überrascht - ich dachte, die Intel-Chips hätten eine anständige FPU, aber ich denke, allgemeine FP -Operationen können immer noch nicht mit handoptimiertem Integer-Code mithalten.

Aktualisiere die folgenden Stormsoul-Vorschläge:

Das Testen der Lösung mit multiplizierter Iteration durch stormsoul ergibt ein Ergebnis von 4 Sekunden. Sie ist zwar viel schneller als die Lösung mit dividierter Iteration, entspricht aber immer noch nicht der optimierten Lösung mit if-Anweisungen.

Durch die Auswahl der Argumente aus einem Pool von 1000 zufällig generierten Zahlen wurde die Zeit für die Geschwindigkeit auf 2 Sekunden verkürzt. Es scheint also von Vorteil zu sein, jedes Mal dasselbe Argument zu haben, es ist jedoch immer noch der schnellste aufgeführte Ansatz.

Das Kompilieren mit -O2 verbesserte die Geschwindigkeiten, aber nicht die relativen Positionen (ich erhöhte die Iterationszahl um den Faktor zehn, um dies zu überprüfen).

Jede weitere Analyse muss sich ernsthaft mit dem Innenleben der CPU-Effizienz befassen (verschiedene Arten der Optimierung, Verwendung von Caches, Verzweigungsvorhersage, welche CPU Sie tatsächlich haben, die Umgebungstemperatur im Raum usw.) meiner bezahlten Arbeit im Weg stehen :-). Es war eine interessante Ablenkung, aber irgendwann wird der Return on Investment für die Optimierung zu gering, um eine Rolle zu spielen. Ich denke, wir haben genug Lösungen, um die Frage zu beantworten (schließlich ging es nicht um Geschwindigkeit).

Weiteres Update:

Dies wird meine letzte Aktualisierung dieser Antwort sein, mit Ausnahme eklatanter Fehler, die nicht von der Architektur abhängig sind. Inspiriert von Stormsouls tapferen Bemühungen zu messen, veröffentliche ich mein Testprogramm (modifiziert gemäß Stormsouls eigenem Testprogramm) zusammen mit einigen Beispielzahlen für alle in den Antworten hier gezeigten Methoden. Denken Sie daran, dass dies eingeschaltet ist eine bestimmte Maschine, Ihre Laufleistung kann variieren, je nachdem, wo Sie sie ausführen (weshalb ich den Testcode veröffentliche).

Mach damit, wie du willst:

#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;
}

Denken Sie daran, dass Sie sicherstellen müssen, dass Sie zum Kompilieren die richtige Befehlszeile verwenden. Insbesondere müssen Sie möglicherweise die Mathematikbibliothek explizit auflisten, damit log10() funktioniert. Die Kommandozeile, die ich unter Debian verwendet habe, war gcc -o testprog testprog.c -lm.

Und in Bezug auf die Ergebnisse ist hier die Rangliste für meine Umgebung:

Optimierungsstufe 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

Optimierungsstufe 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
134
paxdiablo

Die kürzeste Antwort: snprintf(0,0,"%+d",n)-1

26
R..

Pseudo-Algorithmus für binäre Suche, um keine Ziffern von r in v zu erhalten.

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;
26
lakshmanaraj

In einer Schleife durch 10 teilen, bis das Ergebnis Null erreicht. Die Anzahl der Iterationen entspricht der Anzahl der Dezimalstellen.

Angenommen, Sie erwarten 0 Ziffern in einem Nullwert:

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

Constant-Cost-Version, die x86-Assembly und eine Nachschlagetabelle verwendet:

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 );
}

Eine andere, mit einer kleineren Nachschlagetabelle und einer log10-Annäherung aus hier .

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]));
}

Beide nutzen die Tatsache aus, dass on x86 -INT_MIN gleich INT_MIN ist.

Update:

Als Vorschlag werden hier die Timings für die count_bsr und eine etwas schnellere 64-Bit-Routine count_bsr_mod verglichen mit der binären Suche und den binären Chop-Algos, die das zu generierende Testprogramm von Nice paxdiablo verwenden Sets mit einer zufälligen Vorzeichenverteilung. Tests wurden mit gcc 4.9.2 unter Verwendung der Optionen "-O3 -falign-Funktionen = 16 -falign-jumps = 16 -march = corei7-avx" erstellt und auf einem ansonsten ruhenden Sandy-Bridge-System mit deaktivierten Turbo- und Schlafzuständen ausgeführt.

Zeit für bsr mod: 270000 Zeit für bsr: 340000 Zeit für binären Chop: 800000 Zeit für binäre Suche: 770000 Zeit für binäre Suche: 470000 

Quelle für den Test,

#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's 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;
}
6

Sie können Folgendes tun: floor (log10 (abs (x))) + 1 Wenn Sie Zyklen sparen möchten, können Sie nur Vergleiche durchführen

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

Dies vermeidet alle rechenintensiven Funktionen wie Protokollieren oder sogar Multiplikation oder Division. Wenn es nicht inelegant ist, kann dieses durch Einkapseln in eine Funktion ausgeblendet werden. Es ist nicht komplex oder schwer zu behaupten, daher würde ich diesen Ansatz nicht wegen schlechter Kodierungspraxis abweisen. Ich habe das Gefühl, dass ich das Baby mit dem Badewasser wegwerfen würde.

6
Howard May

Von Bit Twiddling Hacks:

Finden Sie die ganzzahlige Protokollbasis 10 einer Ganzzahl auf offensichtliche Weise

Beachten Sie die Reihenfolge der Vergleiche darin.

5
fa.

Hier ist eine abgewickelte binäre Suche ohne Division oder Multiplikation. Abhängig von der Verteilung der Zahlen, die ihm gegeben werden, kann es die anderen mit unrollierten if-Anweisungen geschlagenen schlagen oder nicht, aber sie sollten immer diejenigen schlagen, die Schleifen und Multiplikation/Division/log10 verwenden.

Bei einer gleichmäßigen Verteilung der Zufallszahlen, die den gesamten Bereich umfassen, betrug der Durchschnitt auf meinem Rechner 79% der Ausführungszeit von count_bchop () von paxdiablo, 88% der Zeit von count_ifs () und 97% der Zeit von count_revifs ().

Bei einer Exponentialverteilung (die Wahrscheinlichkeit einer Zahl mit n Ziffern ist gleich der der mit - Ziffern, wobei m n ) count_ifs () und count_revifs () beide schlagen meine Funktion. Ich bin mir nicht sicher warum.

int count_bsearch(int i)
{
    if (i < 0)
    {
        if (i == INT_MIN)
            return 10; // special case for -2^31 because 2^31 can't fit in a two's 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;
        }
    }
}
4
Deadcode

Bei einer Google-Suche bin ich darauf gestoßen: http://www.hackersdelight.org/hdcodetxt/ilog.c.txt

Ein kurzer Benchmark zeigte deutlich, dass die binären Suchmethoden erfolgreich waren. lakshmanarajs - Code ist ziemlich gut, Alexander Korobkas ist ~ 30% schneller, Deadcodes ist noch ein bisschen schneller (~ 10%), aber ich fand die folgenden Tricks aus dem obigen Link eine weitere Verbesserung um 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.
}

Beachten Sie, dass dies Protokoll 10 ist, nicht die Anzahl der Ziffern, also digits = ilog10c(x)+1.

Unterstützt keine Negative, aber das lässt sich leicht mit einem - beheben.

4
jozxyqk
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

Sehr unelegant Aber schneller als alle anderen Lösungen. Integer Division- und FP -Protokolle sind teuer. Wenn Leistung kein Problem ist, ist die log10-Lösung mein Favorit.

2
Wayne Sheppard

Nur ein wenig für C-Sprache anpassen:

floor( log10( abs( (number)?number:1 ) ) + 1 );
    int n = 437788;
    int N = 1; 
    while (n /= 10) N++; 
2
xcramps

Ich weiß, dass ich zu spät komme, aber dieser Code ist + x10 schneller als alle anderen Antworten.

int digits(long long x)
{
    x < 0 ? x = -x : 0;
    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 :
        x < 10000000000 ? 10 : 0;
}

...

int x = -937810;
printf("%d : %d digits\n", x, digits(x));

Aus:

-937810 : 6 digits
1
X Stylish

Eine einfache Methode zum Ermitteln der Länge (dh der Anzahl von Ziffern) einer vorzeichenbehafteten Ganzzahl lautet:

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

Dabei ist n die ganze Zahl, deren Länge Sie ermitteln möchten, und wobei len der Anzahl der Stellen in der ganzen Zahl entspricht. Dies funktioniert für beide Werte von n (negativ oder positiv).

Der Aufruf von abs() ist optional, wenn Sie nur mit positiven Ganzzahlen arbeiten.

0
user2849447

Verwenden Sie NICHT den Boden (log10 (...)). Dies sind Fließkomma-Funktionen und langsame Funktionen, die hinzugefügt werden müssen. Ich glaube, der schnellste Weg wäre diese Funktion:

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;
   }
}

Beachten Sie, dass die von einigen Personen vorgeschlagene binäre Suchversion aufgrund von falschen Vorhersagen der Branche langsamer sein könnte.

BEARBEITEN:

Ich habe ein paar Tests gemacht und einige wirklich interessante Ergebnisse erzielt. Ich habe meine Funktion zusammen mit allen von Pax getesteten Funktionen UND der binären Suchfunktion von lakshmanaraj .. festgelegt. Das Testen wird durch den folgenden Code-Ausschnitt ausgeführt:

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;

Wobei das Feld number [] zufällig generierte Zahlen über den gesamten Bereich des int-Typs enthält (Sperrung MIN_INT). Der Test wurde für jede getestete Funktion im Array THE SAME Numbers [] wiederholt. Der gesamte Test wurde zehnmal durchgeführt, wobei die Ergebnisse über alle Durchgänge gemittelt wurden. Der Code wurde mit GCC 4.3.2 mit dem Optimierungsgrad -O3 kompiliert.

Hier sind die Ergebnisse:

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

Ich muss sagen, dass ich wirklich erstaunt bin. Die binäre Suche funktionierte viel besser als ich dachte. Ich habe herausgefunden, wie GCC diesen Code in asm kompiliert hat. O_O. Jetzt ist das beeindruckend. Es wurde viel besser optimiert, als ich es für möglich hielt, und die meisten Zweige auf wirklich clevere Art und Weise vermieden. Kein Wunder, dass es SCHNELL ist.

0
stormsoul

Für c # gibt es hier eine sehr schnelle und einfache Lösung ...

    private static int NumberOfPlaces(int n)
    {
       //fast way to get number of digits
       //converts to signed string with +/- intact then accounts for it by subtracting 1
       return n.ToString("+#;-#;+0").Length-1;
    }
0
neoscribe

Ich denke, der einfachste Weg wäre:

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

Ziffern gibt die Antwort.

0
Zeeshan

sie können die Anzahl der Ziffern in einer Zahl mithilfe der folgenden Formel ermitteln

0
Anshul garg