Domanda

Dato l'articolo di Wikipedia su Radix Point , come si potrebbe calcolare l'equivalente binario di 10.1 o l'equivalente esadecimale di 17,17? Per il primo, quello che è l'equivalente binario di un decimo? Per questi ultimi, la rappresentazione esadecimale di 17/100?

Sto cercando di più per un algoritmo che per le soluzioni di solo questi due esempi.

È stato utile?

Soluzione

Per convertire decimale 10.1 a binario, separare le parti intere e frazionarie e convertire ogni separatamente.

Per convertire la parte intera, utilizzare divisione intera ripetuto da 2, e quindi scrivere i resti in ordine inverso:

10/2 = 5 restante 0

5/2 = 2 restante 1

2/2 = 1 resto 0

1/2 = 0 resto 1

Risposta: 1010

Per convertire la parte frazionaria, uso ripetuto moltiplicazione per 2, sottraendo fuori la parte intera ad ogni passo. I numeri interi, in ordine di generazione, rappresentano la vostra numero binario:

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

... (ciclo si ripete sempre)

Quindi decimale 0.1 è binario 0,000110011001100 ...

(Per una spiegazione più dettagliata si veda routine dec2bin_i () e dec2bin_f () nel mio articolo http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/ .)

Per esadecimale, utilizzare la stessa procedura, se non con un divisore / moltiplicatore 16 invece di 2. I residui e numeri interi maggiori di 9 deve essere convertito in cifre esadecimali direttamente: 10 diventa A, 11 diventa B, ..., 15 diventa F.

Altri suggerimenti

Un numero di terminazione (un numero che può essere rappresentato da un numero finito di cifre) n 1 in base b 1 , può finire per essere un numero non fatale in una base diversa b 2 . Al contrario, un non-terminante numero in una base b 1 può rivelarsi un numero terminante in base b 2 .

Il numero 0.1 10 quando convertito in binario è un numero non fatale, come è 0,17 10 quando convertito in un numero esadecimale. Ma il numero di terminazione 0,1 3 in base 3, quando convertito in base 10 è la non-terminazione, ripetendo numero 0. (3) 10 (che indica che il numero 3 ripetizioni ). Analogamente, la conversione di 0,1 10 a binario e 0,17 10 in esadecimale, si finisce con il non-terminazione, ripetendo numeri 0.0 (0011) 2 e 0,2 (B851E) 16

A causa di questo, quando si converte un tale numero da una base all'altra, si possono trovare te dover approssimare il numero invece di avere una rappresentazione che è del tutto precisa.

L'algoritmo è abbastanza semplice, ma in pratica si può fare un sacco di modifiche, sia con tabelle di ricerca e registri per accelerarlo. Ma per l'algoritmo di base, si può provare qualcosa di simile:

shift=0;

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

Next digit: 
if v<1.0 && shift==0, output the decimal point
else 
   D=floor(v)
   output D
   v=v-D
v=v*base
shift = shift-1
if (v==0) exit;
goto Next Digit

Si può anche mettere un test in là per arrestare la stampa dopo N cifre per più ripetere decimali.

Il 'equivalente binario' di un decimo è una metà, cioè invece di 1/10 ^ 1, è 1/2 ^ 1.

Ogni cifra rappresenta una potenza di due. Le cifre dietro il punto di radice sono gli stessi, è solo che essi rappresentano 1 sopra la potenza di due:

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

Quindi, per 10.1, dovrete, ovviamente, un '8' e un '2' a fare la parte 10. 1/2 (0,5) è troppo, 1/4 (0.25) è troppo, 1/8 (0,125) è troppo. Abbiamo bisogno di 1/16 (0,0625), che ci lascerà con 0,0375. 1/32 è 0,03,125 mila, così possiamo fare anche questo. Finora abbiamo:

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

Con un errore di 0,00,625 mila. 1/64 (0,015,625 mila) e 1/128 (,0078,125 mila) sono entrambi troppo, 1/256 (,00,390625 millions) funzionerà:

 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

Con un errore di ,00,234375 millions.

Il .1 non può essere espresso esattamente in binario (come 1/3 non può essere espresso esattamente in decimale). A seconda di dove si mette il radix, alla fine si deve fermare, probabilmente rotondo, ed accettare l'errore.

Prima di girarsi con questo alla luce della mia biblioteca GMP, qui è dove ho avuto modo di provare a rendere il codice PHP di Rick Regan generico per qualsiasi base da 2 fino a 36.

Function dec2base_f(ByVal ddecimal As Double, ByVal nBase As Long, ByVal dscale As Long) As String
    Const BASES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 'up to base 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

Function 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top