Ermitteln der Länge einer ganzen Zahl in C

Lesezeit: 9 Minuten

Benutzeravatar von marabunta2048
marabunta2048

Ich würde gerne wissen, wie ich die Länge einer ganzen Zahl in C finden kann.

Zum Beispiel:

  • 1 => 1
  • 25 => 2
  • 12512 => 5
  • 0 => 1

usw.

Wie kann ich das in C machen?

  • Was ist die Definition von “Länge”, wenn die Ganzzahl 0 ist? Negativ?

    – kennytm

    18. Juni 2010 um 9:11 Uhr

  • Siehe stackoverflow.com/questions/679602/…. Es ist fast ein Duplikat, aber nicht genau, da es sich um eine .NET-Frage handelt.

    – ChrisF

    18. Juni 2010 um 9:36 Uhr

  • Die richtige Frage ist nicht die Länge der Ganzzahl, sondern die minimale Anzahl von Dezimalstellen, die benötigt wird, um diese Zahl darzustellen (in einem C int enthalten). log10 ist dein Freund: log10(10000) = 4, +1 die Anzahl der Stellen (log10 muss abgeschnitten werden)… wenn die Zahl negativ ist, brauchst du eins mehr für das – Symbol, wenn du es zählen willst, und log10(-num) (da Log einer negativen Zahl “problematisch” ist).

    – Shin Takezou

    18. Juni 2010 um 9:41 Uhr

  • Wie sicher bist du dir das? log10(10000) wird 4 und nicht 3,999999 zurückgeben …?

    – Keith Thompson

    29. August 2011 um 5:58 Uhr

  • Hmm. Experiment zeigt das log10(10**n) liefert den genauen Wert für Zehnerpotenzen von 1 bis 2**19, zumindest mit gcc und glibc. Aber ich würde mich nicht bei allen Implementierungen darauf verlassen. (** bedeutet Potenzierung; Es gibt keinen solchen Operator in C.)

    – Keith Thompson

    29. August 2011 um 6:02 Uhr

Benutzeravatar von Jordan Lewis
Jordan Lewis

C:

Warum nehmen Sie nicht einfach den Basis-10-Log des Absolutwerts der Zahl, runden ihn ab und addieren eins? Dies funktioniert für positive und negative Zahlen, die nicht 0 sind, und vermeidet die Verwendung von String-Konvertierungsfunktionen.

Das log10, absund floor Funktionen werden bereitgestellt von math.h. Zum Beispiel:

int nDigits = floor(log10(abs(the_integer))) + 1;

Sie sollten dies in eine Klausel packen, die dies sicherstellt the_integer != 0seit log10(0) kehrt zurück -HUGE_VAL entsprechend man 3 log.

Außerdem möchten Sie möglicherweise eins zum Endergebnis hinzufügen, wenn die Eingabe negativ ist, wenn Sie an der Länge der Zahl einschließlich ihres negativen Vorzeichens interessiert sind.

Java:

int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;

NB Die Fließkomma-Natur der Berechnungen, die bei dieser Methode verwendet werden, kann dazu führen, dass sie langsamer ist als ein direkterer Ansatz. In den Kommentaren zu Kangkans Antwort finden Sie einige Diskussionen zur Effizienz.

  • Eigentlich sollten Sie floor verwenden und stattdessen 1 hinzufügen. Math.Ceil(Math.Log(99)) = 2 aber Math.Ceil(Math.Log(10)) = 1. Math.Floor(Math.Log(99)) + 1 = 2 und Math.Floor(Math. Protokoll (10)) = 2

    – Sani Singh Huttunen

    18. Juni 2010 um 9:20 Uhr

  • Die Frage zur Definition der Länge ist nicht ganz klar (Sie hätten also möglicherweise an “Anzahl der Ziffern ohne führende Nullen” denken können), aber ich würde erwarten, dass 0 und -1 eher 1 und 2 als Länge ihrer Zeichendarstellung zurückgeben als -2147483648 und 1.

    – Peter Kirkham

    18. Juni 2010 um 9:40 Uhr

  • @Pete Vielen Dank, dass Sie mich an die Domänenbeschränkung des Protokolls und den negativen Zahlenfall erinnert haben – ich habe meine Antwort bearbeitet.

    – Jordan Lewis

    18. Juni 2010 um 9:51 Uhr


  • +1 schön und kurz – das ist meine bevorzugte Antwort, auch wenn es die langsamste ist – schließlich ist der Geschwindigkeitsunterschied nicht groß und diese Art von Code ist sehr unwahrscheinlich, dass es sich um eine Leistung handelt. Engpass sowieso.

    – Eamon Nerbonne

    18. Juni 2010 um 13:20 Uhr

  • Dies funktioniert nicht für 999999999999999999, eine C-Ganzzahl, die in einen größeren Double-Wert konvertiert wird und somit eine fehlerhafte Anzahl von Ziffern erzeugt. Das OP hat es nicht spezifiziert intnur eine ganze Zahl.

    – chqrlie

    23. November 2015 um 23:08 Uhr

Benutzeravatar von Eamon Nerbonne
Eamon Nerbonne

Bei Interesse an einer schnell und sehr einfach Lösung, die folgende könnte am schnellsten sein (dies hängt von der Wahrscheinlichkeitsverteilung der fraglichen Zahlen ab):

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

int printLen(int x) {
    return x < 0 ? lenHelper(-x) + 1 : lenHelper(x);
}

Während es vielleicht keine Preise für die genialste Lösung gewinnt, ist es trivial zu verstehen und auch trivial auszuführen – also ist es schnell.

Auf einem Q6600 mit MSC habe ich dies mit der folgenden Schleife bewertet:

int res = 0;
for(int i = -2000000000; i < 2000000000; i += 200) res += printLen(i);

Diese Lösung dauert 0,062 s, die zweitschnellste Lösung von Pete Kirkham mit einem Smart-Logarithmus-Ansatz dauert 0,115 s – fast doppelt so lange. Bei Zahlen um 10000 und darunter ist das Smart-Log jedoch schneller.

Auf Kosten der Klarheit können Sie Smart-Log zuverlässiger schlagen (zumindest auf einem Q6600):

int lenHelper(unsigned x) { 
    // this is either a fun exercise in optimization 
    // or it's extremely premature optimization.
    if(x >= 100000) {
        if(x >= 10000000) {
            if(x >= 1000000000) return 10;
            if(x >= 100000000) return 9;
            return 8;
        }
        if(x >= 1000000) return 7;
        return 6;
    } else {
        if(x >= 1000) {
            if(x >= 10000) return 5;
            return 4;
        } else {
            if(x >= 100) return 3;
            if(x >= 10) return 2;
            return 1;
        }
    }
}

Diese Lösung dauert bei großen Zahlen immer noch 0,062 s und verschlechtert sich bei kleineren Zahlen auf etwa 0,09 s – in beiden Fällen schneller als der Smart-Log-Ansatz. (gcc macht schnelleren Code; 0,052 für diese Lösung und 0,09 s für den Smart-Log-Ansatz).

  • Ich schaudere, wenn ich daran denke, wie die zweite Version aussehen würde, die vollständig mit dem ternären Operator geschrieben wurde …

    – Eamon Nerbonne

    18. Juni 2010 um 13:22 Uhr

  • Wenn dies verwendet würde, um lange Listen von Zahlen zu kauen, würde die Menge an Verzweigungscode Chaos mit der CPU verursachens branch prediction and not produce the fastest execution IIch habe Angst.

    – Lloyd Crawley

    23. Oktober 2013 um 8:52 Uhr

  • In meinem Benchmark ist es immer noch die schnellste Lösung – beachten Sie, dass alle anderen integralen Lösungen auch mehrere Zweige benötigen, und die einzige wirkliche Alternative eine Int-to-Double-Konvertierung mit einem Gleitkommaprotokoll ist (was, wie sich herausstellt, auch nicht billig ist). .

    – Eamon Nerbonne

    23. Oktober 2013 um 16:15 Uhr

  • @earthdan: Diese Lösung ist in Ordnung, aber aufgrund der Teilungen ziemlich langsam. Es verwendet auch immer mehr Zweige als die zweite Version dieses Codes und im Durchschnitt mehr als die erste hier gepostete Lösung. Außerdem ist diese Lösung ziemlich schlau (auf eine schlechte Art und Weise), da der Grund, warum sie funktioniert, nicht ganz offensichtlich ist. Wenn Sie eine kurze und offensichtliche Lösung wünschen, verwenden Sie stackoverflow.com/a/3068412/42921; Wenn Sie eine schnelle und offensichtliche Lösung wünschen, verwenden Sie diese. Kann mir den Anwendungsfall für stackoverflow.com/a/6655759/2382629 nicht vorstellen (obwohl es natürlich eine lustige intellektuelle Übung ist!)

    – Eamon Nerbonne

    17. März 2014 um 12:55 Uhr


Benutzeravatar von zed_0xff
zed_0xff

int get_int_len (int value){
  int l=1;
  while(value>9){ l++; value/=10; }
  return l;
}

und der zweite funktioniert auch für negative Zahlen:

int get_int_len_with_negative_too (int value){
  int l=!value;
  while(value){ l++; value/=10; }
  return l;
}

  • Ich mag das. Keine temporären Zeichenpuffer mit Annahmen über die Größe.

    – Noufal Ibrahim

    18. Juni 2010 um 9:13 Uhr

  • Schnell und elegant funktioniert dies jedoch nicht für negative Zahlen. Ich weiß nicht, ob das ein Problem für das Frageposter ist

    – Jamie Wong

    18. Juni 2010 um 9:16 Uhr

  • es wird. Versuche es. es wird 1 zurückgegeben

    – zed_0xff

    19. Juni 2010 um 10:10 Uhr

  • Du hast Recht – es wird in der Tat :-). Es wäre für mich klarer (und nicht langsamer), diesen Fall eher über eine if-Rückgabe als über eine Negation zu unterscheiden.

    – Eamon Nerbonne

    21. Juni 2010 um 7:54 Uhr

Sie können eine Funktion wie folgt schreiben:

unsigned numDigits(const unsigned n) {
    if (n < 10) return 1;
    return 1 + numDigits(n / 10);
}

Benutzeravatar von Fritz G. Mehner
Fritz G. Mehner

Länge von n:

length =  ( i==0 ) ? 1 : (int)log10(n)+1;

  • Sie sollten wahrscheinlich das Runden über Casting vermeiden und stattdessen einen expliziteren (auch als portierbaren und konsistenten) Rundungsansatz wählen.

    – Chris Lutz

    18. Juni 2010 um 9:18 Uhr

  • wie ist casting umgesetzt? wie kann eine funktion wie boden realisiert werden? (Wir gehen von einem Prozessor mit IEEE in Hardware oder durch einen mathematischen Coprozessor oder die Verfügbarkeit von Softwarefunktionen aus, um dieselbe Funktion auszuführen, die normalerweise auf fp-fähigen Prozessoren vorhanden ist) … am Ende (int) ist portabel und konsistent in die meisten Fälle (ich wage zu sagen, alle Fälle, um die wir uns normalerweise kümmern)

    – Shin Takezou

    18. Juni 2010 um 9:48 Uhr

  • Wie in anderen Beiträgen erwähnt, schlägt dies fehl, wenn n = 0 ist

    – Jamie Wong

    18. Juni 2010 um 9:59 Uhr

  • @Lutz: Welche Art von Portabilität kaufen Sie, wenn Sie davon ausgehen, dass das Casting von Double nach Int nicht definiert ist? Gibt es eigentlich eine entsprechende Plattform wo das der Fall ist?

    – Eamon Nerbonne

    18. Juni 2010 um 13:34 Uhr

  • @Chris Lutz Wenn es sich um eine standardkonforme C-Implementierung handelt, gehorcht sie Wenn ein endlicher Wert vom Typ Real Floating in einen anderen Integer-Typ als _Bool konvertiert wird, wird der Bruchteil verworfen (dh der Wert wird in Richtung Null gekürzt).

    – Peter Kirkham

    18. Juni 2010 um 17:44 Uhr

Benutzeravatar von sam hocevar
sam hocevar

Ein richtiges snprintf Implementierung:

int count = snprintf(NULL, 0, "%i", x);

  • Sie sollten wahrscheinlich das Runden über Casting vermeiden und stattdessen einen expliziteren (auch als portierbaren und konsistenten) Rundungsansatz wählen.

    – Chris Lutz

    18. Juni 2010 um 9:18 Uhr

  • wie ist casting umgesetzt? wie kann eine funktion wie boden realisiert werden? (Wir gehen von einem Prozessor mit IEEE in Hardware oder durch einen mathematischen Coprozessor oder die Verfügbarkeit von Softwarefunktionen aus, um dieselbe Funktion auszuführen, die normalerweise auf fp-fähigen Prozessoren vorhanden ist) … am Ende (int) ist portabel und konsistent in die meisten Fälle (ich wage zu sagen, alle Fälle, um die wir uns normalerweise kümmern)

    – Shin Takezou

    18. Juni 2010 um 9:48 Uhr

  • Wie in anderen Beiträgen erwähnt, schlägt dies fehl, wenn n = 0 ist

    – Jamie Wong

    18. Juni 2010 um 9:59 Uhr

  • @Lutz: Welche Art von Portabilität kaufen Sie, wenn Sie davon ausgehen, dass das Casting von Double nach Int nicht definiert ist? Gibt es eigentlich eine entsprechende Plattform wo das der Fall ist?

    – Eamon Nerbonne

    18. Juni 2010 um 13:34 Uhr

  • @Chris Lutz Wenn es sich um eine standardkonforme C-Implementierung handelt, gehorcht sie Wenn ein endlicher Wert vom Typ Real Floating in einen anderen Integer-Typ als _Bool konvertiert wird, wird der Bruchteil verworfen (dh der Wert wird in Richtung Null gekürzt).

    – Peter Kirkham

    18. Juni 2010 um 17:44 Uhr

Benutzeravatar von IVlad
IVlad

Die Anzahl der Ziffern einer ganzen Zahl x ist gleich 1 + log10(x). Sie können also Folgendes tun:

#include <math.h>
#include <stdio.h>

int main()
{
    int x;
    scanf("%d", &x);
    printf("x has %d digits\n", 1 + (int)log10(x));
}

Oder Sie können eine Schleife ausführen, um die Ziffern selbst zu zählen: Führen Sie eine ganzzahlige Division durch 10 durch, bis die Zahl 0 ist:

int numDigits = 0;
do
{
    ++numDigits;
    x = x / 10;
} while ( x );

Bei der Rückkehr muss man etwas aufpassen 1 wenn die ganze Zahl ist 0 in der ersten Lösung und Sie möchten vielleicht auch negative ganze Zahlen behandeln (arbeiten Sie mit -x wenn x < 0).

  • Ja, schön einfach do Schleife.

    – chux – Wiedereinsetzung von Monica

    23. November 2015 um 23:07 Uhr

1419400cookie-checkErmitteln der Länge einer ganzen Zahl in C

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy