Pergunta

Dada artigo da Wikipedia sobre Radix Ponto , como seria um calcular o equivalente binário de 10,1 ou o equivalente hexadecimal de 17,17? Para o primeiro, o que é o equivalente binário de um décimo? Para este último, a representação hexadecimal de 17/100?

Eu estou olhando mais para um algoritmo de soluções para apenas esses dois exemplos.

Foi útil?

Solução

Para converter decimal 10,1 para binário, separe os inteira e fracionária e converter cada um separadamente.

Para converter a parte inteira, o uso repetido inteiro divisão por 2, e em seguida, escrever os remanescentes na ordem inversa:

2/10 = 5 restante 0

5/2 = 2 restante 1

2/2 = 1 restante 0

02/01 = 0 restante 1

Resposta: 1010

Para converter a parte fraccionada, o uso repetido de multiplicação por dois, subtraindo a parte inteira em cada passo. As peças inteiras, na ordem da geração, representam o número binário:

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 se repete sempre)

Assim decimal 0.1 é binário ,000110011001100 ...

(Para uma explicação mais detalhada ver rotinas dec2bin_i () e dec2bin_f () em meu artigo http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/ .)

Para hexadecimal, utilizar o mesmo procedimento, excepto com um divisor / multiplicador de 16 em vez de 2. O vasilhame e peças número inteiro maior do que 9 deve ser convertido para dígitos hexadecimais directamente: 10 torna-se um, 11 torna-se B, ..., 15 torna-se F.

Outras dicas

Um número de terminação (um número que pode ser representado por um número finito de dígitos) n 1 na base b 1 , pode acabar por ser um número não encerra em uma base diferente b 2 . Por outro lado, um número de não-encerramento em uma base de b 1 pode vir a ser um número de terminação na base b 2 .

O número 0,1 10 quando convertida em binário é um número de não-encerramento, como é 0,17 10 quando convertidos para um número hexadecimal. Mas, o número de terminação 0,1 3 na base 3, quando convertido para a base 10 é o não-terminal, repetindo-se o número 0. (3) 10 (significando que o número 3 repetições ). Do mesmo modo, a conversão de 0,1 10 para binário e 0,17 10 em hexadecimal, acaba-se com o não-terminal, os números de repetição de 0,0 (0011) 2 e 0,2 (B851E) 16

Devido a isso, ao converter um número tal de uma base para outra, você pode encontrar-se ter que aproximar o número em vez de ter uma representação que é completamente preciso.

O algoritmo é bastante simples, mas na prática você pode fazer um monte de ajustes tanto com tabelas de pesquisa e logs para acelerá-lo. Mas para o algoritmo básico, você pode tentar algo como isto:

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

Você também pode colocar um teste lá para parar a impressão depois de N dígitos para números decimais mais repetidos.

O 'equivalente binário' de um décimo é metade, ou seja, em vez de 1/10 ^ 1, é 1/2 ^ 1.

Cada dígito representa uma potência de dois. Os dígitos atrás do ponto de raiz são as mesmas, é só que eles representam 1 sobre o poder de dois:

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

Assim, para 10,1, você obviamente precisa de um '8' e '2' para fazer a parte 10. 1/2 (0,5) é demasiado, 1/4 (0,25) é demasiada, 1/8 (0,125) é demasiada. Precisamos de 1/16 (0,0625), o que vai nos deixar com 0,0375. 1/32 é 0,03125, para que possamos levar isso também. Até agora, temos:

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

Com um erro de 0,00625. 1/64 (0,015625) e 1/128 (0,0078125) são ambos muito, 1/256 (0,00390625) funcionará:

 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

Com um erro de 0,00234375.

O .1 não podem ser expressos exatamente em binário (como 1/3 não podem ser expressos exatamente em decimal). Dependendo de onde você colocar a sua raiz, você acabará por ter de parar, provavelmente rodada, e aceitar o erro.

Antes de eu mexer com isso, à luz da minha biblioteca GMP, aqui é onde eu tenho que tentar tornar o código PHP do Rick Regan genérico para qualquer base de 2 até 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top