001
31.03.2003, 02:09 Uhr
Hans
Library Walker (Operator)
|
Hi,
in Informatik- und Programmierlehrbüchern findet man meisst irgendwo in Kapitel, das sich mit unterschiedlichen Zahlensystemen beschäftigt. Unter anderem erfährt man dort, das sich eine Zahl als eine Summe von Potenzen darstellen lässt. So ist z.B. die Zahl 123.456 in der Potenzform darstellbar als:
1*10^2 + 2*10^1 + 3*10^0 + 4*10^(-1) + 5*10^(-2) + 6*10^(-3)
Hierbei fällt auf, das bei Dezimalzahlen immer eine Multiplikation mit 10 im Spiel ist, und (dem Wesen einer Summe entsprechend) eine Addition. Die prinzipielle Vorgehensweise, um eine beliebige Zahl aus einem String in den gewünschten Datentyp zu konvertieren ist deshalb folgende:
1. Eine Variable mit 0 initialisieren, wo in der am Ende die umgewandelte Zahl drin steht. 2. Man nehme von links her ein Zeichen aus dem String und stelle fest, ob es ein Ziffernzeichen ist. 2a. Wenn es ein Ziffernzeichen ist, wird es in den Zahlenwert umgewandelt, den es repräsentiert. D.h. aus dem ASCII-Code für '2' wird der Zahlenwert Zwei. 2b. Die zuvor initialisierte Variable wird mit 10 multipliziert, und anschliessend die eben umgewandelte Zahl dazu gezählt (addiert). 3. Wenn es kein Ziffernzeichen ist, wird die Umwandlungsaktion beendet.
Das gilt bis hierher für ganze Zahlen genauso, wie für gebrochene. Ein Dezimalpunkt, bzw. einem Komma dient als Hinweis, dass man jetzt ein wenig anders weitermachen muss.
4. Der gebrochene Anteil muss erst mal in einer eigenen Variablen gepuffert werden. Er wird erst am Ende der Umwandlung per Addition dem ganzzahligen Anteil hinzugefügt. 5. Die weiteren Ziffern werden wie in Punkt 2, bzw. 2a behandelt. Nur anstelle der multiplikation in Punkt 2b muss jetzt eine Division erfolgen. Das kommt daher, das die Nachkommastellen in der Potenzdarstellung ein Minuszeichen im Exponenten (also vor der Hochzahl) haben. Und das bedeutet eben, das man durch 10 teilen muss.
Alternativ kann man bei Punkt 4 auch so weitermachen, wenn das Komma kommt: 4a. Das Komma wird überlesen 4b. Wir machen ganz genau so weiter, wie bisher, zusätzlich werden noch die Ziffern gezählt, die hinter dem Komma stehen. 4c. Am Ende wird sooft durch 10 geteilt, wie Nachkommastellen gezählt wurden. Bei 3 Stellen nach dem Komma wären das drei Divisionen durch 10.
Soweit die theoretische Erklärung, die mir hoffentlich einigermassen gelungen ist. In einem Programm sieht das ganze ungefähr so aus:
C++: |
/* Datei: zahlein2.cpp
Zum testen einer Routine für Zahlenumwandlungen
*/
#include <stdio.h> #include <stdlib.h> #include <string.h>
double zahlein(char *s);
int main() { double zahl; char s[20];
printf ("Bitte geben Sie eine Zahl ein: "); fgets (s, 19, stdin); zahl=zahlein(s); printf ("Die eingegebene Zahl ist: %lf\n", zahl);
//getch(); return 0; }
double zahlein(char *s) { int ii, j, vz, nk; double w;
ii=j=vz=nk=0; w=0;
while (s[ii]==' ') // mögliche führende Leerzeichen überlesen ii++; // Evtl. vorhandenes Vorzeichen überprüfen und merken if (s[ii]=='-') { vz=1; ii++; } a: // Solange, wie Ziffernzeichen da sind while (s[ii]>'/' && s[ii]<':') // diese in den Zahlenwert umwandeln und { w = w * 10. + ( s[ii]-'0'); // zur Zahl hinzu fügen ii++; // nächstes Zeichen if (nk) j++; // Wenn es Nachkommastellen sind, werden sie gezählt } if (s[ii]=='.' || s[ii]==',') // Komma behandlung { nk++; // Flag zur Kennzeichnung von Nachkommastellen ii++; /* Komma überlesen */ goto a; } for ( ; j>0; j--) // Die Zahl entsprechend der Nachkommastellen w /= 10. ; // durch 10 teilen return( vz ? -w : w); // Die Zahl vorzeichengerecht an den Aufrufer liefern } /* Ausschnitt aus der ASCII-Tabelle: Zeichen : / 0 1 2 3 4 5 6 7 8 9 : Code (dez) : 47 48 49 50 51 52 53 54 55 56 57 58 (hex) : 2f 30 31 32 33 34 35 36 37 38 39 3a */
|
Hier hab ich die zweite Möglichkeit verwendet. Möglicherweise ist sie etwas zu Rechenintensiv, aber das dürfte sich angesichts der aktuellen Taktfrequenzen erst bei sehr großen Datenmengen bemerkbar machen, denke ich mal.
Hans -- Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung. Dieser Post wurde am 31.03.2003 um 02:14 Uhr von Hans editiert. |