170 Stimmen

Effizienter Weg zur Bestimmung der Anzahl der Ziffern in einer ganzen Zahl

Was ist ein sehr effizient wie man die Anzahl der Ziffern einer ganzen Zahl in C++ bestimmen kann?

14 Stimmen

In welcher Basis? 2? 10?

4 Stimmen

Ich würde es gerne zur Basis 10 machen

1 Stimmen

Ich habe einmal eine ähnliche Frage gestellt: Wie kann man die erste Ziffer einer int-Zahl ermitteln? In den Antworten wurden viele der gleichen Methoden wie unten beschrieben verwendet. Hier ist der Link, falls er für Ihre Aufgabe relevant ist [ [stackoverflow.com/questions/701322/]](http://stackoverflow.com/questions/701322/])

124voto

Vitali Punkte 3128

Nun, der effizienteste Weg, vorausgesetzt, Sie kennen die Größe der Ganzzahl, wäre ein Lookup. Das sollte schneller sein als der viel kürzere logarithmusbasierte Ansatz. Wenn Sie nicht über die Zählung der "-" kümmern, entfernen Sie die + 1.

#include <climits>

// 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 64-bit numbers
template <>
int numDigits(int64_t x) {
    if (x == INT64_MIN) return 19 + 1;
    if (x < 0) return digits(-x) + 1;

    if (x >= 10000000000) {
        if (x >= 100000000000000) {
            if (x >= 10000000000000000) {
                if (x >= 100000000000000000) {
                    if (x >= 1000000000000000000)
                        return 19;
                    return 18;
                }
                return 17;
            }
            if (x >= 1000000000000000)
                return 16;
            return 15;
        } 
        if (x >= 1000000000000) {
            if (x >= 10000000000000)
                return 14;
            return 13;
        }
        if (x >= 100000000000)
            return 12;
        return 11;
    }
    if (x >= 100000) {
        if (x >= 10000000) {
            if (x >= 100000000) {
                if (x >= 1000000000)
                    return 10;
                return 9;
            }
            return 8;
        }
        if (x >= 1000000)
            return 7;
        return 6;
    }
    if (x >= 100) {
        if (x >= 1000) {
            if (x >= 10000)
                return 5;
            return 4;
        }
        return 3;
    }
    if (x >= 10)
        return 2;
    return 1;
}

// partial specialization optimization for 32-bit numbers
template<>
int numDigits(int32_t x)
{
    if (x == INT32_MIN) 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];
}

86voto

Skizz Punkte 66931

Der einfachste Weg ist, dies zu tun:

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

log10 ist definiert in <cmath> ou <math.h> . Sie müssen ein Profil erstellen, um zu sehen, ob es schneller ist als die anderen hier geposteten. Ich bin mir nicht sicher, wie robust dies in Bezug auf die Fließkommagenauigkeit ist. Außerdem ist das Argument unsigned als negative Werte und log nicht wirklich mischen.

77voto

Brad Punkte 821

Vielleicht habe ich die Frage missverstanden, aber reicht das nicht aus?

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

35voto

squelart Punkte 10785
int digits = 0; while (number != 0) { number /= 10; digits++; }

Hinweis: "0" hat 0 Ziffern! Wenn die "0" 1 Ziffer haben soll, verwenden Sie:

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

(Danke Kevin Fegan)

Benutzen Sie schließlich einen Profiler, um herauszufinden, welche der Antworten auf Ihrem Rechner schneller ist...

14voto

wugoat Punkte 105

In eine Zeichenkette konvertieren und dann integrierte Funktionen verwenden

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X