3 Stimmen

Wie berechnet man Fließkommazahlen mit einer anderen Radix als 10?

Angesichts des Wikipedia-Artikels über Radix-Punkt Wie würde man das binäre Äquivalent von 10,1 oder das hexadezimale Äquivalent von 17,17 berechnen? Was ist das binäre Äquivalent eines Zehntels für die erstgenannte Zahl? Wie lautet die hexadezimale Darstellung von 17/100?

Ich suche eher nach einem Algorithmus als nach Lösungen für nur diese beiden Beispiele.

6voto

Rick Regan Punkte 3329

Um die Dezimalzahl 10,1 in Binär umzuwandeln, trennen Sie den Ganzzahlen- und den Dezimalteil und wandeln Sie beide separat um.

Um den Ganzzahlenteil umzuwandeln, verwenden Sie wiederholte Ganzzahldivision durch 2 und schreiben Sie die Reste in umgekehrter Reihenfolge auf:

10/2 = 5 Rest 0

5/2 = 2 Rest 1

2/2 = 1 Rest 0

1/2 = 0 Rest 1

Antwort: 1010

Um den Dezimalteil umzuwandeln, verwenden Sie wiederholte Multiplikation mit 2 und subtrahieren Sie bei jedem Schritt den Ganzzahlenteil. Die Ganzzahlenteile, in der Reihenfolge ihrer Entstehung, stellen Ihre Binärzahl dar:

0,1 * 2 = 0,2

0,2 * 2 = 0,4

0,4 * 2 = 0,8

0,8 * 2 = 1,6

0,6 * 2 = 1,2

0,2 * 2 = 0,4

0,4 * 2 = 0,8

... (Zyklus wiederholt sich endlos)

Also ist die Dezimalzahl 0,1 binär 0,000110011001100...

(Für eine ausführlichere Erklärung siehe die Funktionen dec2bin_i() und dec2bin_f() in meinem Artikel http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/.)

Für Hexadezimal verwenden Sie dasselbe Verfahren, nur mit einem Divisor/Multiplikator von 16 anstelle von 2. Reste und Ganzzahlenteile größer als 9 müssen direkt in Hexadezimalziffern umgewandelt werden: 10 wird zu A, 11 wird zu B, ... , 15 wird zu F.

3voto

SPWorley Punkte 11140

Der Algorithmus ist ziemlich einfach, aber in der Praxis können Sie viele Anpassungen sowohl mit Suchtabellen als auch mit Logarithmen vornehmen, um ihn zu beschleunigen. Aber für den grundlegenden Algorithmus können Sie etwas Ähnliches wie dies versuchen:

shift=0;

while v>=basis,  v=v/basis, shift=shift+1;  

Nächste Ziffer: 
if v<1.0 && shift==0, geben Sie den Dezimalpunkt aus
sonst 
   D=floor(v)
   geben Sie D aus
   v=v-D
v=v*basis
shift = shift-1
if (v==0) beenden;
gehe zu Nächste Ziffer

Sie können auch einen Test einbauen, um das Drucken nach N Stellen für längere wiederholende Dezimalzahlen zu stoppen.

3voto

Roshan Punkte 1075

Eine endende Zahl (eine Zahl, die durch eine endliche Anzahl von Ziffern dargestellt werden kann) n1 zur Basis b1 kann sich zu einer nicht endenden Zahl zur anderen Basis b2 entwickeln. Umgekehrt kann eine nicht endende Zahl zur Basis b1 sich als endende Zahl zur Basis b2 herausstellen.

Die Zahl 0,110, wenn sie in Binär übersetzt wird, ist eine nicht endende Zahl, ebenso wie 0,1710, wenn sie in eine hexadezimale Zahl umgewandelt wird. Aber die endende Zahl 0,13 zur Basis 3 wird, wenn sie in Basis 10 umgewandelt wird, zur nicht endenden, wiederholenden Zahl 0,(3)10 (was bedeutet, dass die Zahl 3 sich wiederholt). Ähnlich ergibt die Umrechnung von 0,110 in Binär und 0,1710 in Hexadezimal die nicht endenden, wiederholenden Zahlen 0,0(0011)2 und 0,2(B851E)16

Aufgrund dessen kann es beim Umrechnen einer solchen Zahl von einer Basis in eine andere erforderlich sein, die Zahl zu approximieren, anstatt eine vollkommen genaue Darstellung zu haben.

1voto

Chris Arguin Punkte 11608

Das 'binäre Äquivalent' von einem Zehntel ist ein Halb, d.h. anstatt von 1/10^1 ist es 1/2^1.

Jede Ziffer repräsentiert eine Potenz von zwei. Die Ziffern hinter dem Dezimalpunkt sind die gleichen, es ist nur so, dass sie 1 über der Potenz von zwei darstellen:

 8 4 2 1 . 1/2 1/4 1/8 1/16 

Also für 10.1, benötigen Sie offensichtlich eine '8' und eine '2', um den 10-Teil zu bilden. 1/2 (0,5) ist zu viel, 1/4 (0,25) ist zu viel, 1/8 (0,125) ist zu viel. Wir brauchen 1/16 (0,0625), was uns auf 0,0375 lässt. 1/32 ist 0,03125, also können wir das auch nehmen. Bisher haben wir:

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32
 1 0 1 0    0   0   0   1     1

Mit einem Fehler von 0,00625. 1/64 (0,015625) und 1/128 (0,0078125) sind beide zu viel, 1/256 (0,00390625) wird funktionieren:

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256
 1 0 1 0    0   0   0   1     1    0   0     1

Mit einem Fehler von 0,00234375.

Das .1 kann nicht genau im Binärcode ausgedrückt werden (genauso wie 1/3 nicht genau im Dezimalsystem ausgedrückt werden kann). Je nachdem, wo Sie Ihr Dezimalzeichen setzen, müssen Sie letzten Endes anhalten, wahrscheinlich runden und den Fehler akzeptieren.

0voto

bugmagnet Punkte 7433

Vor dem Anpassen dieses Codes im Licht meiner GMP-Bibliothek hier ist, wo ich versucht habe, Rick Regans PHP-Code für jede Basis von 2 bis 36 generisch zu machen.

Funktion dec2base_f(ByVal ddecimal As Double, ByVal nBase As Long, ByVal dscale As Long) As String
    Const BASES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 'bis Basis 36
    Dim digitCount As Long
    Dim wholeNumber As Double
    Dim digit As String * 1
    digitCount = 0
    dscale = max(dscale, Len(CStr(ddecimal)) - Len("0."))
    Dim baseary_f As String
    baseary_f = "0."
    Do While ddecimal > 0 And digitCount < dscale
        ddecimal = ddecimal * nBase
        digit = Mid$(BASES, Fix(ddecimal) + 1)
        baseary_f = baseary_f & digit '"1"
        ddecimal = ddecimal - Fix(ddecimal)
        digitCount = digitCount + 1
    Loop
    dec2base_f = baseary_f
End Function

Funktion base2dec_f(ByVal baseary_f As String, nBase As Double) As Double
    Const BASES As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Dim decimal_f As Double
    Dim i As Long
    Dim c As Long
    For i = Len(baseary_f) To Len("0.") + 1 Step -1
        c = InStr(BASES, Mid$(baseary_f, i, 1)) - 1
        decimal_f = decimal_f + c
        decimal_f = decimal_f / nBase
    Next
    base2dec_f = decimal_f
End Function

Debug.Print base2dec_f(dec2base_f(0.09, 2, 200), 2) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 8, 200), 8) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 16, 200), 16) --> 0.09

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X