Forum: Compiler & IDEs Anzahl Stellen einer Zahl


von Dennis (Gast)


Lesenswert?

Hallo,
ich möchte die Anzahl der Stellen einer Zahl bestimmen.
Bei 123456 soll zum Beispiel 6 herauskommen.
Gab es nicht Funktionen wie length() oder so ähnlich?
Gruß,
Dennis

von UBoot-Stocki (Gast)


Lesenswert?

Hi,

wie wärs mit einer Funktion,

- die solange durch 10 teilt, bis die "Restzahl" 0 ist?

- die die Zahl in einen String wandelt und dann mittels "strlen" die 
Länge bestimmt ?

Gruß

Andreas

von Christian (Gast)


Lesenswert?

...oder den Logarithmus zur Basis 10 ausrechnen und dann das Ergebnis 
aufrunden. Wird allerdings auf einem µC nicht sehr effizient.

Grüße,
 Christian

von Florian (Gast)


Lesenswert?

Das Effizienteste ist mit Sicherheit eine Verschachtelung von 
Bedingungen (also if etc.), da - bei ganzzahligen Datentypen - die 
maximale Anzahl der Ziffern wohl bekannt ist.

8-bit 0 - 255, also maximal 3 Ziffern
16-bit 0 - 65535, also max. 5 Ziffern
24-bit 0 - 16777215, also max. 8 Ziffern
32-bit 0 - 4294967295, also max. 10 Ziffern

usw.

Die Divisionen sind langsamer.

Also etwas in der Art, wie

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

usw.

von Simon K. (simon) Benutzerseite


Lesenswert?

Das könnte man auch noch in eine For-Schleife packen ;)

von yalu (Gast)


Lesenswert?

> Das könnte man auch noch in eine For-Schleife packen ;)

Genau! Und dann mit -O3 kompilieren, um den Schleifen-Overhead und die
Multiplikationen wieder wegzuoptimieren ;) ;)

von Dirk (Gast)


Lesenswert?

char s[6];
int z=12345
int len;

sprintf(s,"%d",z);
len = strlen(s);

von Guenther B. (Firma: gbs-Consulting) (gboelter)


Lesenswert?

#include <stdio.h>
#include <string.h>

int main (void) {

    int i;
    int n;

    printf("Bitte geben Sie eine Zahl ein : ");
    scanf("%d",&i);

    n = anzahl(i);
    printf ( "Die Zahl %i besteht aus %i Ziffern!\n", i, n );
}


anzahl (arg1)
{

    int zeichen;
    char buffer[100];
    sprintf(buffer, "%d", arg1);

    zeichen = strlen(buffer);

    return zeichen;

}

von yalu (Gast)


Lesenswert?

Wenn man schon mit Kanonen auf Spatzen schießt (sprintf :-)), kann man
auf strlen verzichten, da die Länge als Abfallprodukt geliefert wird:
1
int anzahl(unsigned int n) {
2
  char buffer[11];
3
  return sprintf(buffer, "%d", n);
4
}

von yalu (Gast)


Lesenswert?

Stopp, Fehler entdeckt:

s/%d/%u/

:-)

von Guenther B. (Firma: gbs-Consulting) (gboelter)


Lesenswert?

yalu wrote:
> Wenn man schon mit Kanonen auf Spatzen schießt (sprintf :-)), kann man
> auf strlen verzichten, da die Länge als Abfallprodukt geliefert wird:

Stimmt, keine Frage. Aber ich wollte auch nur den vorangegangnen Code 
ein wenig erlaeutern. Aus der Ursprungsfrage von Dennis schliesse ich 
naemlich, das er in C/C++ nicht so bewandert ist.

Meinen Beispielcode hatte ich zudem gerade rein zufaellig im Editor ...

Guenther
Davao City, Philippines, Planet Earth

von And the winner is (Gast)


Lesenswert?

if ( x < 10 )
  return 1;
else if ( x < 100 )
  return 2;
else if ( x < 1000 )
  return 3;
else if ( x < 10000 )
  return 4;
return 5;


  CMP.W  #0xa, R15
  JC  ??main_0
  MOV.W  #0x1, R12
  RET
??main_0:
  CMP.W  #0x64, R15
  JC  ??main_1
  MOV.W  #0x2, R12
  RET
??main_1:
  CMP.W  #0x3e8, R15
  JC  ??main_2
  MOV.W  #0x3, R12
  RET
??main_2:
  CMP.W  #0x2710, R15
  JC  ??main_3
  MOV.W  #0x4, R12
  RET
??main_3:
  MOV.W  #0x5, R12
  RET

Nicht alles was schick aussieht, ist auch effizient.

von Rolf Magnus (Gast)


Lesenswert?

Hast du denn eine effizientere Lösung?

von yalu (Gast)


Lesenswert?

Vielleicht sollte man an dieser Stelle einmal zwischen Speicher- und
Laufzeiteffizenz unterscheiden:

- Am speichereffizientesten sind sicher die Logarithmus- und die
  sprintf-Lösung, wenn man die Mathebibliothek bzw. die
  sprintf-Funktion (und den benötigten Puffer) sowieso schon an
  anderer Stelle im Programm benutzt.

- Sind diese Voraussetzungen nicht gegeben, ist wahrscheinlich Simons
  Schleife eine gute Wahl. Die ist auch laufzeitmäßig nicht schlecht,
  vor allem dann, wenn das Zielsystem einen schnellen Multiplizierer
  hat.

- Am schnellsten ist aber sicher die Lösung mit einzelnen
  if-Anweisungen wie von Florian, oder (noch schneller) so:
1
  if(n < 100000) {
2
    if(n < 1000) {
3
      if(n < 100) {
4
        if(n < 10)
5
          return 1;
6
        return 2;
7
      }
8
      return 3;
9
    }
10
    if(n < 10000)
11
      return 4;
12
    else
13
      return 5;
14
  }
15
  if(n < 100000000) {
16
    if(n < 10000000) {
17
      if(n < 1000000)
18
        return 6;
19
      return 7;
20
    }
21
    return 8;
22
  }
23
  if(n < 1000000000)
24
    return 9;
25
  else
26
    return 10;
  Dies ist für 32-Bit-Zahlen. Für größere oder kleiner Wertebereiche
  muss der Code natürlich angepasst werden.

von Simon K. (simon) Benutzerseite


Lesenswert?

yalu wrote:
>> Das könnte man auch noch in eine For-Schleife packen ;)
>
> Genau! Und dann mit -O3 kompilieren, um den Schleifen-Overhead und die
> Multiplikationen wieder wegzuoptimieren ;) ;)

Achwas, die Hauptsache ist doch, dass es im Quelltext schön aussieht ;) 
;)

@ And the winner is (Gast):
Verstehe deinen Einwand nicht so ganz, was gibt's denn an dem Code zu 
meckern? Entspricht doch genau dem (zumindest von mir) erwarteten Code: 
Vergleiche und bedingte Jumps...

PS: Die Sache mit dem strlen ist ja wohl Mega-Quatsch... Erst alles 
durch Dividieren/Modulo mit 10 in einen String umwandeln und 
anschließend nochmal von vorne zählen, wieviele Stellen > 0 entstanden 
sind.

Da "erzeugt" man doch in einem Zwischenschritt Informationen, die man 
nachher eh "wegschmeißt"...

PPS: @Yalu vor mir: Die Version sieht richtig gut aus. Wenn ich das 
richtig sehe, werden sogar unnötige Vergleiche direkt vermieden, wenn 
sie gar nicht mehr wahr werden können.

von yalu (Gast)


Lesenswert?

Ja. Man unterteilt den Wertebereich wiederholt in zwei Teile, so dass
in jedem möglichst gleichviele Stellenzahlen liegen. Der erste
Vergleich trennt die Zahlen nach solchen mit der Stellenzahl 1..5 und
solchen mit der Stellenzahl 5..10. Für jede dieser Hälften wird das
Verfahren entsprechend fortgesetzt, so dass man schließlich mit
maximal 4 Vergleichen zum Ziel kommt.

Übungsaufgabe für den geneigten Leser: Man formuliere das ganze kürzer
und eleganter als
a) Schleife
b) Rekursion
:-)

von Guenther B. (Firma: gbs-Consulting) (gboelter)


Lesenswert?

Das ist ja alles schoen und nett, aber die Frage von Dennis war doch 
wohl

> ich möchte die Anzahl der Stellen einer Zahl bestimmen.
> Bei 123456 soll zum Beispiel 6 herauskommen.
> Gab es nicht Funktionen wie length() oder so ähnlich?

der hat doch von Geschwindigkeit und dergleichen ueberhaupt nichts 
geschrieben, der wollte - meiner bescheidenen Meinung nach - nur eine 
simple Alternative zu length() haben, und das ist nun mal der 'Trick' 
mit sprintf.

Klar sind Eure Ansaetze super, aber das war doch ueberhaupt nicht das 
Thema,

von Sven (Gast)


Lesenswert?

Ja, solange nur die Datentypen char und int verwendet werden. Wenn ein 
Long verwendet werden soll, muss man die Funktion noch weiter ausbauen, 
da man hier den formatstring %ld verwenden muss.

von Simon K. (simon) Benutzerseite


Lesenswert?

Guenther Boelter wrote:
> Klar sind Eure Ansaetze super, aber das war doch ueberhaupt nicht das
> Thema,

Und? Man kann doch ruhig weiterspinnen, wenn die Frage des Threadopeners 
eigentlich völlig geklärt ist.

von Peter D. (peda)


Lesenswert?

Mir stellt sich die Frage nach der Sinnhaftigkeit, die Länge einer Zahl 
zu bestimmen, ohne sie ausgeben zu wollen.

Wenn man sie zur Ausgabe umwandelt fällt die Länge ja automatisch ab 
(Mitzählen) bzw. kann per strlen einfachst ermittelt werden.

Deshalb werde ich mich hüten, für derart Sinnloses hier Code 
reinzustellen (wäre schade um die Mühe).


Peter

von Rolf Magnus (Gast)


Lesenswert?

> Mir stellt sich die Frage nach der Sinnhaftigkeit, die Länge einer Zahl
> zu bestimmen, ohne sie ausgeben zu wollen.
>
> Wenn man sie zur Ausgabe umwandelt fällt die Länge ja automatisch ab
> (Mitzählen) bzw. kann per strlen einfachst ermittelt werden.

Vielleicht will er ja die Länge bereits vor der Ausgabe wissen statt 
nachher, z.B. weil er es rechtsbündig ausgeben will und dazu wissen 
will, wo er links anfangen muß.

> Deshalb werde ich mich hüten, für derart Sinnloses hier Code
> reinzustellen (wäre schade um die Mühe).

Du hast doch überhaupt keine Ahnung, wozu der Ursprungsposter das will. 
Wie kannst du da wissen, ob es sinnlos ist?

von Peter D. (peda)


Lesenswert?

Rolf Magnus wrote:

> Vielleicht will er ja die Länge bereits vor der Ausgabe wissen statt
> nachher, z.B. weil er es rechtsbündig ausgeben will und dazu wissen
> will, wo er links anfangen muß.

1.
Man macht Wandlung und rechtsbündige Ausgabe gleichzeitig:
printf("%6d", i);

2.
Man macht alles nacheinander(itoa, strlen, lcd_locate, lcd_puts).


Beides benötigt leider nicht, die Länge vor der Wandlung zu kennen.


Peter

von yalu (Gast)


Lesenswert?

Peter Dannegger schrieb:

> Deshalb werde ich mich hüten, für derart Sinnloses hier Code
> reinzustellen (wäre schade um die Mühe).

Dass du dir keinen Sinn in Dennis Frage vorstellen kannst, hat geneu
einen der folgenden beiden Gründe:

- Diesen Sinn gibt es tatsächlich nicht.

- Der Sinn liegt außerhalb deines Gedankenhorizonts.


Mir ist vollkommen klar, was Dennis damit machen will: Nämlich
folgendes zahlentheoretische Problem lösen:

  Gegegeben seien zwei Funktionen f und g von N in N (N ist die Menge
  der natürlichen Zahlen).

  s(n) sei die Stellenanzahl von n in Dezimalschreibweise.

  Gesucht ist die kleinste Zahl n aus N, für die gilt:

    f(n) = s(g(n))

Da f und g ziemlich komplizierte Funktionen sind, will Dennis das
Problem per Computer durch Ausprobieren lösen. Dazu braucht er sehr
schnelle Implementationen von f, g und s. Für f und g hat er die schon
gefunden, sonst hätte er danach gefragt. Aber s fehlte ihm noch,
deswegen seine Anfrage.

Zum Glück hat er unter den vielen Lösungsvorschlägen einen geeigneten
gefunden (sonst hätte er den Grund gepostet, warum die Vorschläge
nichts taugen) und lässt nun gerade seinen Rechner nudeln.

Jeder, der eine Lösung wusste, sie aber nicht gepostet hat, hat mit
seinem Verhalten den wissenschaftlichen Fortschritt gebremst.

                                                                ;-)

von Guenther B. (Firma: gbs-Consulting) (gboelter)


Lesenswert?

Nun kommt mal wieder mit den Fuessen auf die Erde, das ist hier doch 
kein Kindergarten. Da hat jemand eine durchaus interessante Frage 
gestellt, die es jedem frei steht sie zu beantworten.

Und was macht ihr draus: Meiner ist groesser, laenger, dicker ....

Habt ihr sonst nix zu tun?

von Simon K. (simon) Benutzerseite


Lesenswert?

Guenther Boelter wrote:
> Da hat jemand eine durchaus interessante Frage
> gestellt, die es jedem frei steht sie zu beantworten.
Ja, EBEN.

> Und was macht ihr draus: Meiner ist groesser, laenger, dicker ....
Programmierer überbieten sich halt gern in Sachen "Wer hat den besseren 
Code". Immerhin kann man so voneinander lernen und unter Umständen 
völlig andere Algorithmen kennen lernen um ein bestimmtes Problem zu 
lösen...

> Habt ihr sonst nix zu tun?
Das frage ich mich im Bezug auf dich.

Beitrag #5088904 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.