2009-09-09 5 views
30

Wie bekomme ich, was die Ziffern einer Zahl in C++ sind, ohne es in Zeichenfolgen oder Zeichenarrays umzuwandeln?Wie erhalten Sie die Ziffern einer Zahl, ohne sie in ein String/Char-Array umzuwandeln?

+0

Do u Anzahl der Stellen erhalten möchten oder alle Ziffern in dieser Zahl in separaten Variablen oder Integer-Array ? – vpram86

+1

Was meinst du? Möchten Sie die Anzahl der Ziffern zählen? Möchten Sie die fünfte Ziffer aus einer Nummer extrahieren? –

+0

Können Sie ein Beispiel geben? –

Antwort

39

Die folgenden druckt die Ziffern in der Reihenfolge der Bedeutung aufsteigend (das heißt Einheiten, dann zehn, usw.):

do { 
    int digit = n % 10; 
    putchar('0' + digit); 
    n /= 10; 
} while (n > 0); 
+1

Wenn (n == 0) keine Ziffern gedruckt werden. – xtofl

+0

@xtofl: Danke, korrigiert. –

+0

Erwarten Sie etwas, wenn n == 0? Ich würde erwarten, dass dies ein ungültiger Input und somit ein undefiniertes Verhalten oder eine Assert ist. –

0

Verwenden Sie eine Sequenz von mod 10 und div 10 Operationen (unabhängig von der Syntax in C++), um die Ziffern nacheinander anderen Variablen zuzuweisen.

In Pseudo-Code

lsd = number mod 10 
number = number div 10 
next lsd = number mod 10 
number = number div 10 

etc ...

schmerzhaft! ... aber keine Zeichenfolgen oder Zeichenfelder.

1

Erste Ziffer (am wenigsten signifikant) = Nummer% 10, zweite Ziffer = Stock (Nummer/10)% 10, 3. Ziffer = Stock (Nummer/100)% 10.

etc
+0

Schöne und allgemeine Lösung. Die Floating-Point-Funktion "floor" zu durchlaufen macht jedoch wenig Sinn. Werfen Sie auch einen Blick auf Martins Lösung! – xtofl

+0

Nun ... ich würde eigentlich floor() nicht verwenden, aber ich habe das eingeschlossen, falls das OP floats oder was auch immer benutzt ... nur um es explizit zu machen. Wenn er int benutzt, dann ist das kein Problem. – mpen

6

Etwas wie folgt aus:

int* GetDigits(int num, int * array, int len) { 
    for (int i = 0; i < len && num != 0; i++) { 
    array[i] = num % 10; 
    num /= 10; 
    } 
} 

Die Mod 10 ist sehen Sie die Ziffern erhalten. Die div 10s werden die Nummer voranbringen.

+4

Sie könnten nicht 'len' haben - es ist besser zu beenden, wenn' num' auf 0 geht. –

+0

Guter Punkt. Brauchen Sie, um sicherzustellen, dass wir das Array nicht überlaufen. Eine Überprüfung hinzugefügt, ob num 0 ist. –

+2

Dies kann leicht umgestaltet werden, um Ziffern für jede Basis zu generieren. Für jetzt erzeugt es Ziffern nur für die Basis 10 ... – SadSido

8

Sie wollen etwas, was wie das?

int n = 0; 
    std::cin>>n; 

    std::deque<int> digits; 
    if(n == 0) 
    { 
     digits.push_front(0); 
     return 0; 
    } 

    n = abs(n); 
    while(n > 0) 
    { 
     digits.push_front(n % 10); 
     n = n /10; 
    } 
    return 0; 
+3

+1 für die Verwendung von Std-Containern anstelle von Arrays –

+0

ja, +1 für Std: D – ntcong

+1

winziges Problem für die Zahl Null, obwohl ... – xtofl

13

Da jeder läutet, ohne die Frage zu kennen.
Hier ist mein Versuch Vergeblichkeit:

#include <iostream> 

template<int D> int getDigit(int val)  {return getDigit<D-1>(val/10);} 
template<>  int getDigit<1>(int val) {return val % 10;} 

int main() 
{ 
    std::cout << getDigit<5>(1234567) << "\n"; 
} 
+0

Nice one! Und es funktioniert auch für Null! – xtofl

+1

Obwohl die Laufzeitkomplexität O (sizeof (int)^2) bei der Berechnung aller Ziffern ist. Hmm .... Und woher weißt du, an welcher Stelle zu beginnen? – xtofl

+0

Technisch ist die Laufzeitkomplexität O (1), da sich der Code für verschiedene Eingabewerte nicht ändert. Hinweis: Die große O-Notation ist ein Maß dafür, wie die Laufzeit in Bezug auf Eingabeargumente skaliert. –

19

Was floor(log(number))+1?

Mit n Ziffern und unter Verwendung von Basis b Sie eine beliebige Anzahl von bis zu pow(b,n)-1 ausdrücken können. Um die Anzahl der Ziffern einer Zahl x in der Basis b zu erhalten, können Sie die Umkehrfunktion der Potenzierung verwenden: base-b logarithm. Um nicht ganzzahlige Ergebnisse zu verarbeiten, können Sie den Trick floor()+1 verwenden.

PS: Dies funktioniert für Ganzzahlen, nicht für Zahlen mit Dezimalzahlen (in diesem Fall sollten Sie wissen, welche Genauigkeit der von Ihnen verwendete Typ hat).

+1

+1 log mit log. – dmeister

+2

Nach zwei Jahren verstehe ich immer noch nicht, warum diese Antwort nicht so gut war wie die anderen. – tunnuz

+0

Sie können nicht 'ceil (log (x))' anstelle von 'floor (log (x)) + 1' verwenden, da' ceil' falsche Werte zurückgibt, wenn 'log (x)% 1 == 0' (zB wenn 'x = 100' erwarten Sie _3_ (mit' floor + 1') anstelle von _2_ (mit nur 'ceil') – cruizh

11

Ich habe viele Antworten gesehen, aber sie alle vergessen do {...} while() Schleife zu verwenden, die eigentlich die kanonische Weise, dieses Problem zu lösen und 0 ordnungsgemäß zu behandeln.

Meine Lösung basiert auf this eins von Naveen.

int n = 0; 
std::cin>>n; 

std::deque<int> digits; 
n = abs(n); 
do { 
    digits.push_front(n % 10); 
    n /= 10; 
} while (n>0); 
0

Nicht so wie Martin York Antwort cool, aber Adressierung nur ein willkürliches ein Problem:

Sie können eine positive ganze Zahl größer als Null drucken eher einfach mit Rekursion:

#include <stdio.h> 
void print(int x) 
{ 
    if (x>0) { 
     print(x/10); 
     putchar(x%10 + '0'); 
    } 
} 

Dieser Wille die niedrigstwertige Ziffer zuletzt ausdrucken. vor

0

Jahren, als Antwort auf die oben gestellten Fragen würde ich den folgenden Code schreiben:

int i2a_old(int n, char *s) 
{ 
    char d,*e=s;//init begin pointer 
    do{*e++='0'+n%10;}while(n/=10);//extract digits 
    *e--=0;//set end of str_number 
    int digits=e-s;//calc number of digits 
    while(s<e)d=*s,*s++=*e,*e--=d;//reverse digits of the number 
    return digits;//return number of digits 
} 

Ich denke, dass die Funktion printf (...) funktioniert so ähnlich.

Jetzt werde ich dies schreibe:

int i2a_new(int n, char *s) 
{ 
    int digits=n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10; 
    char *e=&s[digits];//init end pointer 
    *e=0;//set end of str_number 
    do{*--e='0'+n%10;}while(n/=10);//extract digits 
    return digits;//return number of digits 
} 

Vorteile: Lookup-Tabelle indipendent; C, C++, Java, JavaScript, PHP-kompatibel; Anzahl der Ziffern erhalten, min comparisons: 3; Anzahl der Ziffern erhalten, max comparisons: 4; schneller Code; ein Vergleich ist sehr einfach und schnell: cmp reg, immediate_data -> 1 CPU-Uhr.

+0

Ihr Code ist kaputt. Er akzeptiert negative Zahlen, funktioniert aber nicht mit ihnen und macht Annahmen über die Größe von 'int' – LtWorf

3

Integer-Version ist trivial:

int fiGetDigit(const int n, const int k) 
{//Get K-th Digit from a Number (zero-based index) 
    switch(k) 
    { 
     case 0:return n%10; 
     case 1:return n/10%10; 
     case 2:return n/100%10; 
     case 3:return n/1000%10; 
     case 4:return n/10000%10; 
     case 5:return n/100000%10; 
     case 6:return n/1000000%10; 
     case 7:return n/10000000%10; 
     case 8:return n/100000000%10; 
     case 9:return n/1000000000%10; 
    } 
    return 0; 
} 
0

wie ein Array, das alle einzelnen Ziffern in etwas holen - zwei Varianten:

int i2array_BigEndian(int n, char a[11]) 
{//storing the most significant digit first 
    int digits=//obtain the number of digits with 3 or 4 comparisons 
    n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10; 
    a+=digits;//init end pointer 
    do{*--a=n%10;}while(n/=10);//extract digits 
    return digits;//return number of digits 
} 

int i2array_LittleEndian(int n, char a[11]) 
{//storing the least significant digit first 
    char *p=&a[0];//init running pointer 
    do{*p++=n%10;}while(n/=10);//extract digits 
    return p-a;//return number of digits 
} 
3

einfache Rekursion:

#include <iostream> 

// 0-based index pos 
int getDigit (const long number, int pos) 
{ 
    return (pos == 0) ? number % 10 : getDigit (number/10, --pos); 
} 

int main (void) { 
    std::cout << getDigit (1234567, 4) << "\n";  
} 
+0

Brillant einfach und prägnant –

3

Diese Lösungen sind alles rekursiv oder iterativ. Könnte ein direkterer Ansatz ein wenig effizienter sein?

Von links nach rechts:

int getDigit(int from, int index) 
{ 
    return (from/(int)pow(10, floor(log10(from)) - index)) % 10; 
} 

Von rechts nach links:

int getDigit(int from, int index) 
{ 
    return (from/pow(10, index)) % 10; 
} 
Verwandte Themen