2009-02-16 18 views
33

Ich fürchte, es gibt eine einfache und offensichtliche Antwort auf diese Frage. Ich muss bestimmen, wie viele Stellen eine Anzahl von Elementen breit ist, so dass ich jede Artikelnummer mit der Minimum Nummer der führenden Nullen auffüllen kann, die erforderlich sind, um die Ausrichtung beizubehalten. Zum Beispiel möchte ich keine führenden Nullen, wenn die Summe < 10 ist, 1, wenn es zwischen 10 und 99 usw.Wie kann ich die Ziffern in einer Ganzzahl ohne eine Zeichenfolge zählen?

Eine Lösung wäre, die Elementanzahl in eine Zeichenfolge zu konvertieren und dann Zeichen zu zählen. Yuck! Gibt es einen besseren Weg?

Edit: Ich hätte nicht gedacht, die common logarithm zu verwenden (ich wusste nicht, dass so etwas existiert). Also, nicht offensichtlich - für mich - aber auf jeden Fall einfach.

+1

Obwohl die Logarithmus Lösung der meist up Stimmen, meiner Meinung nach der Zeichenfolge Umwandlung (die überraschenderweise nur einmal vorgeschlagen wurde) ist der bessere. Es spiegelt genau Ihre Absicht wider und es besteht die Möglichkeit, dass Sie eine universelle Komponente schreiben können, die das für alle Arten von Gegenständen (nicht nur Zahlen) tut. –

Antwort

51

Dies sollte es tun:

int length = (number ==0) ? 1 : (int)Math.log10(number) + 1; 
+0

er sagte, es war für eine Zählung. was bedeutet, dass die Domain über die natürlichen Zahlen hinaus geht, nein? also keine Notwendigkeit für eine negative Überprüfung. –

+1

Als ich das letzte Mal überprüft habe, hat die Zahl Null eine Ziffer, nicht Null. Also sollte nicht = = 0 Länge = 1 bedeuten? –

+0

lol. Duh. behoben. –

0

Eine Lösung von Basis 10 Logarithmus vorgesehen ist, ein bisschen übertrieben.

4

Sie können eine while-Schleife verwenden, die als ein Logarithmus wahrscheinlich schneller sein wird, weil dies nur Integer-Arithmetik verwendet:

int len = 0; 
while (n > 0) { 
    len++; 
    n /= 10; 
} 

ich es als eine Übung für den Leser überlassen, diesen Algorithmus zu justieren Null zu handhaben und negative Zahlen.

+0

Dies ist ein guter Kompromiss. Ein "halbherziges Protokoll (n)". Es wird effizienter als das Konvertieren in Zeichenfolge, da die Konvertierung dies als Teil des Algorithmus verwendet. – gbarry

+0

fyl2x ist nur etwa 20-100 Zyklen. div dauert etwa 40, so dass es nur Fälle von 3-4 Ziffern dauert, bevor dieser Algorithmus gefährdet ist, langsamer als ein Protokoll zu sein. In den besten Fällen ist das Protokoll schneller als ein Schritt durch diese Schleife ... – jheriko

+0

@jheriko: Guter Punkt. Für die rohe Leistung vermute ich, dass sich Ihre statische Array-Lösung oder sogar eine Sequenz von Inline-Vergleichen mit unmittelbaren Werten als die schnellste erweisen könnte. Aber wirklich, es spaltet Haare an dieser Stelle! –

0

Sie können durchschleifen und löschen um 10, zählen Sie die Anzahl der Male, die Sie Schleife;

int num = 423; 
int minimum = 1; 
while (num > 10) { 
    num = num/10; 
    minimum++; 
} 
12
int length = (int)Math.Log10(Math.Abs(number)) + 1; 

Sie können für das negative Vorzeichen berücksichtigen müssen ..

+1

+1, aber dies schlägt fehl, wenn Nummer == 0. Sie müssen dies besonders beachten. –

4

Wenn Sie Pad, um die Zahl in .Net werden, dann

num.ToString().PadLeft(10, '0') 

könnte tun, was Sie wollen .

+1

Meine Interpretation ist, dass er eine * Liste * von Zahlen hat, und er möchte die kleineren auffüllen, um die Breite des größten zu vergleichen. Er muss also noch herausfinden, was für PadLeft als erster Parameter übergeben werden soll. –

1

Da eine Zahl keine führenden Nullen enthält, konvertieren Sie sie trotzdem, um sie hinzuzufügen. Ich bin mir nicht sicher, warum Sie so sehr versuchen, es zu vermeiden, um die Länge zu finden, wenn das Endergebnis sowieso eine Schnur sein muss.

+0

Ich mag es, alternative Lösungen zu erkunden. Manchmal lerne ich Dinge - wie log10. – Metaphile

+0

Ich stimme zu, es ist gut, andere Wege zu lernen. Ich konnte einfach nicht verstehen, warum du das in einem so offensichtlichen Fall tun würdest, wenn es nicht nötig war. :-) Wie ich schon sagte, wenn Sie wissen, dass das Endergebnis eine Zeichenfolge sein wird, warum sollten Sie Zeit damit verschwenden, einen Weg zu finden, um nicht weiterzumachen und die Konvertierung durchzuführen? –

0

Okay, ich kann nicht widerstehen: verwenden /=:

#include <stdio.h> 

int 
main(){ 
     int num = 423; 
     int count = 1; 
     while(num /= 10) 
       count ++; 
     printf("Count: %d\n", count); 
     return 0; 
} 
534 $ gcc count.c && ./a.out 
Count: 3 
535 $ 
11

Eine effizientere Lösung als wiederholte Teilung wiederholt werden würde, wenn Aussagen mit vervielfacht ... z (Wobei n die Zahl, deren Anzahl der Stellen erforderlich ist)

unsigned int test = 1; 
unsigned int digits = 0; 
while (n >= test) 
{ 
    ++digits; 
    test *= 10; 
} 

Wenn es eine vernünftige Obergrenze für die Elementanzahl ist (zB der 32-Bit-Bereich eines unsigned int) dann eine noch bessere Weg ist, Vergleichen Sie mit Mitgliedern eines statischen Arrays, z

// this covers the whole range of 32-bit unsigned values 
const unsigned int test[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; 

unsigned int digits = 10; 
while(n < test[digits]) --digits; 
+0

Ich denke, dies ist die klarste und effizienteste Lösung. Ihr Array sollte jedoch mit 0 beginnen, da 0 1 Ziffer hat. –

+0

Aus praktischer Sicht ist die Nachschlagetabelle die absolut beste Lösung. Das Multiplizieren ist die zweitbeste Lösung, da es weniger Zeit benötigt als die Protokoll- oder die Divisionsversion. –

+0

Ich habe gerade festgestellt, dass es einen Bug in der Lookup-Version gibt. Wenn n größer als oder gleich 1000000000 (10 Ziffern) ist, werden Sie vom Ende des Arrays fallen. –

2

Ich hätte einen Kommentar gepostet, aber mein Rep-Score wird mir diese Unterscheidung nicht gewähren.

Alles, was ich war, darauf hinzuweisen wollte, dass, obwohl die Log (10) eine sehr elegante (sprich: sehr wenige Zeilen Code) ist Lösung, ist es wahrscheinlich die auf dem Prozessor ein am meisten zu besteuern ist.

Ich denke, Jhericos Antwort ist wahrscheinlich die effizienteste Lösung und sollte daher als solche belohnt werden.

Vor allem, wenn Sie für eine Menge von Zahlen tun dies gehen werden ..

+0

danke für die Sicherung, aber wenn die Mehrheit die logarithmische Lösung bevorzugen, ist es ihre Wahl. Es mag langsam sein, aber es ist einfacher. :) – jheriko

+0

ja, ich bin überrascht zu sehen, wie viele für die Log-Lösung gewählt haben (nicht, dass es eine schreckliche ist) – user67143

+0

Ja, das ist ein guter Punkt zu erhöhen, eine, die ich glaube, viele ignoriert. Und willkommen im "Kommentarclub"! ;-) – Cerebrus

Verwandte Themen