Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Umwandlung Binaerzahl in Dezimal + Exponent

38 views
Skip to first unread message

Martin Eckel

unread,
Nov 5, 2011, 12:23:57 PM11/5/11
to
Hallo,

ich programmiere in Assembler und möchte eine Zahl auf einem
angeschlossenen Display ausgeben. Hierzu muß ich sie natürlich in
Dezimal wandeln und zwar in die Richtung sechs gültige Ziffern plus
Exponent (der Zahlenbereich ist ziemlich groß).

Welche Ansätze gibts hierfür in Assembler?

Gruß,
Martin

Robert Rohling

unread,
Nov 5, 2011, 3:34:50 PM11/5/11
to
Martin Eckel <martin...@t-online.de> wrote in news:j93nv7$f45$1@dont-
email.me:
Wie wärs z.B. mit ner Binär-Tabelle für alle Zehnerstellen, 10^99...10^0.
Und die vom Ausgangswert subtrahieren bis es nimmer geht.

Gruß R.R.



--
Ich bin unschuldig, ich hab sie nicht gewählt!

Martin Eckel

unread,
Nov 5, 2011, 5:28:23 PM11/5/11
to
Am 05.11.2011 20:34, schrieb Robert Rohling:
> Wie wärs z.B. mit ner Binär-Tabelle für alle Zehnerstellen, 10^99...10^0.
> Und die vom Ausgangswert subtrahieren bis es nimmer geht.

Hmja, von oben anfangen, dann hab ich auch gleich meine gültigen Ziffern...

Wahrscheinlich das beste...

Gruß,
Martin

Stefan Reuther

unread,
Nov 6, 2011, 6:55:59 AM11/6/11
to
Die gleichen wie in jeder anderen Programmiersprache auch.

Mit der C-Funktion 'frexp' kannst du eine Gleitkommazahl in Mantisse und
Binär-Exponent zerlegen. Quelltext für diese Funktion ist im Netz zuhauf
zu finden, auf x86 gibt es dafür eine Assembler-Instruktion (fxtract),
alternativ kann man auch direkt auf der Repräsentation der Gleitkomma-
zahl arbeiten.

Aus dem Binärexponent "B" bekommt man einen Dezimalexponenten "D" durch
Nutzung von D/B = log(2)/log(10), wobei log(2)/log(10) durch 19728/65536
approximiert werden kann. Bei mir sieht das in C so aus:
/* Eingang: Gleitkommazahl c */
int exp2, exp10;
long double divi;
frexp(c, &exp2);
exp10 = exp2 * 19728L / 65536;
divi = ipow(10, exp10);
if (divi > c && c) {
divi /= 10;
--exp10;
}
c /= divi;
/* jetzt ist c \in [0,10) */
Das sollte trivial in eine Assemblersprache deiner Wahl übersetzbar
sein. Eine Zahl aus [0,10) lässt sich dann einfach durch wiederholtes
Multiplizieren und Subtrahieren in Ziffern formatieren.


Stefan

Volker Birk

unread,
Nov 6, 2011, 12:24:27 PM11/6/11
to
Ist es x86? Dann ist das hier für Faule:

http://webster.cs.ucr.edu/AoA/Windows/HTML/AdvancedArithmetica6.html#1000296

Viele Grüsse,
VB.
--
"If /dev/null is fast in web scale I will use it."

http://www.mongodb-is-web-scale.com/

Florian Weimer

unread,
Nov 7, 2011, 1:32:39 AM11/7/11
to
* Martin Eckel:

> ich programmiere in Assembler und möchte eine Zahl auf einem
> angeschlossenen Display ausgeben. Hierzu muß ich sie natürlich in
> Dezimal wandeln und zwar in die Richtung sechs gültige Ziffern plus
> Exponent (der Zahlenbereich ist ziemlich groß).

Soll die Gleitkommazahl, die der ausgegebene Dezimalzahl am nähesten
liegt, wieder die Ausgangszahl sein? Soll 2/5 als 0.2 ausgegeben
werden?

Dann liegt die Schwierigkeit sicherlich nicht in der Umsetzung in
Assembler. 8-)

Martin Eckel

unread,
Nov 7, 2011, 2:23:12 AM11/7/11
to
Am 06.11.2011 18:24, schrieb Volker Birk:
> Ist es x86? Dann ist das hier für Faule:

Nein, ist für einen Signalprozessor.

Trotzdem danke.

Gruß,
Martin

Martin Eckel

unread,
Nov 7, 2011, 2:27:55 AM11/7/11
to
Hallo,

Am 06.11.2011 12:55, schrieb Stefan Reuther:
> c /= divi;

Da fängts schon an: der DSP, auf dem ich programmiere, kann nicht ohne
weiteres dividieren (okay, es gibt einen Befehl, konditionale
Subtraktion, damit kann man durch wiederholte Ausführung das nachbilden).

Ich denke, ich werde die Zehnerpotenzen als Binärzahlen ablegen und
nacheinander abziehen.

Ich könnte auch die C-Bibliothek dazulinken und das ganze innerhalb C
rechnen, das wäre natürlich viel einfacher. Aber da ich dann nicht genau
weiß, wie lange diese Rechnung braucht, wollte ich das Programm in
reinem Assembler lassen.

Gruß,
Martin

Stefan Reuther

unread,
Nov 7, 2011, 1:17:06 PM11/7/11
to
Martin Eckel wrote:
> Am 06.11.2011 12:55, schrieb Stefan Reuther:
>> c /= divi;
>
> Da fängts schon an: der DSP, auf dem ich programmiere, kann nicht ohne
> weiteres dividieren (okay, es gibt einen Befehl, konditionale
> Subtraktion, damit kann man durch wiederholte Ausführung das nachbilden).

Dann multiplizierst du eben mit dem Inversen. Der Divisor ist als
10^exp10 berechnet, das Inverse kannst du dann eben als 0.1^exp10
rechnen (da musst du nur mit der Genauigkeit etwas mehr aufpassen).

> Ich denke, ich werde die Zehnerpotenzen als Binärzahlen ablegen und
> nacheinander abziehen.

Bei einem begrenzten Wertebereich ist das sicher sinnvoll. Für Dinge wie
"16-bit-Zahlen formatieren auf einem 8-bitter ohne Division" hab ich das
auch schon so gemacht.

Allerdings schriebst du "der Zahlenbereich ist ziemlich groß". Um alle
Zahlen zwischen 1.0e+300 und 1.0e-300 formatieren zu können, bräuchtest
du dann eine Tabelle mit 600 Zehnerpotenzen, die du absuchen musst. Für
den Aufwand kannst du eine Menge rechnen, da sollten sogar ein paar in
Software realisierte Divisionen drin sein.


Stefan

Martin Eckel

unread,
Nov 8, 2011, 3:04:44 AM11/8/11
to
Am 07.11.2011 19:17, schrieb Stefan Reuther:
> Allerdings schriebst du "der Zahlenbereich ist ziemlich groß". Um alle
> Zahlen zwischen 1.0e+300 und 1.0e-300 formatieren zu können,

Hmja, wir hatten wohl eine unterschiedliche Vorstellung von einem großen
Zahlenbereich ;-)

Es handelt sich um eine Ganzzahl mit 64 Bit... da ich auf dem Prozessor
normal nur 32 Bit rechne, empfand ich das als groß...

So laufe ich von 1E18 bis 1E0.

Das ganze funktioniert inzwischen auch - nachdem ich mir die Haare
gerauft habe.

Schön wenn das Beispiel in der Online-Hilfe der Entwicklungssoftware
"wie vergleicht man zwei 64-bit Zahlen" fehlerhaft ist.
Darauf bin ich natürlich als letztes gekommen. Aber so ist das, wenn man
sich das Denken abnehmen läßt.

Gruß,
Martin

Stefan Reuther

unread,
Nov 8, 2011, 12:40:31 PM11/8/11
to
Martin Eckel wrote:
> Am 07.11.2011 19:17, schrieb Stefan Reuther:
>> Allerdings schriebst du "der Zahlenbereich ist ziemlich groß". Um alle
>> Zahlen zwischen 1.0e+300 und 1.0e-300 formatieren zu können,
>
> Hmja, wir hatten wohl eine unterschiedliche Vorstellung von einem großen
> Zahlenbereich ;-)
>
> Es handelt sich um eine Ganzzahl mit 64 Bit... da ich auf dem Prozessor
> normal nur 32 Bit rechne, empfand ich das als groß...

Gut, für Ganzzahlen kannst du dann auch mein Geschreibsel mit 'frexp'
usw. ignorieren. Das galt für Floating-Point.

Für Ganzzahlen ist es wahrscheinlich nicht wirklich sinnvoll, das noch
weiter zu optimieren.

> Schön wenn das Beispiel in der Online-Hilfe der Entwicklungssoftware
> "wie vergleicht man zwei 64-bit Zahlen" fehlerhaft ist.
> Darauf bin ich natürlich als letztes gekommen. Aber so ist das, wenn man
> sich das Denken abnehmen läßt.

Ach was, das ist Stand der Technik. Ich hab mit meinem ersten Assembler-
routinchen auf der neuen Plattform einen Assembler-Bug gefunden. Ich
hätte jetzt nicht gedacht, dass ARM 'ldrex' und 'strex' so exotisch
sind, daraus baut man sich ein 'cmpxchg' zusammen, aber dass das kracht,
weil der Assembler da einen ungültigen Befehlscode draus assembliert...


Stefan

0 new messages