简体   繁体   中英

How would I convert a number represented as an array of digits from base-2^k to binary?

I have an algorithm that can simulate converting a binary number to a decimal number by hand. What I mean by this is that each number is represented as an array of digits (from least-to-most-significant) rather than using a language's int or bigint type.

For example, 42 in base-10 would be represented as [2, 4], and 10111 in base-2 would be [1, 1, 1, 0, 1].

Here it is in Python.

def double(decimal):
    result = []
    carry = 0
    for i in range(len(decimal)):
        result.append((2 * decimal[i] + carry) % 10)
        carry = floor((2 * decimal[i] + carry) / 10)
    if carry != 0:
        result.append(carry)
    return result

def to_decimal(binary):
    decimal = []
    for i in reversed(range(len(binary))):
        decimal = double(decimal)
        if binary[i]:
            if decimal == []:
                decimal = [1]
            else:
                decimal[0] += 1
    return decimal

This was part of an assignment I had with an algorithms class a couple of semesters ago, and he gave us a challenge in his notes claiming that we should be able to derive from this algorithm a new one that could convert a number from base-2^k to binary. I dug this up today and it's been bothering me (read: making me feel really rusty), so I was hoping someone would be able to explain how I would write a to_binary(number, k) function based on this algorithm.

Base 2^k has digits 0, 1, ..., 2^k - 1 .

For example, in base 2^4 = 16 , we'd have the digits 0, 1, 2, ..., 10, 11, 12, 13, 14, 15 . For convenience, we use letters for the bigger digits: 0, 1, ..., A, B, C, D, E, F .

So let's say you want to convert AB to binary. The trivial thing to do is convert it to decimal first, since we know how to convert decimal to binary:

AB = B*16^0 + A*16^1 
   = 11*16^0 + 10*16^1
   = 171

If you convert 171 to binary, you'll get:

10101011

Now, is there a shortcut we can use, so we don't go through base 10? There is.

Let's stop at this part:

AB = B*16^0 + A*16^1 
   = 11*16^0 + 10*16^1

And recall what it takes to convert from decimal to binary: do integer division by 2, write down the remainders, write the remainders in reverse order in the end:

number after integer division by 2 | remainder after integer division by 2
--------------------------------------------------------------------------
                                 5 | 1
                                 2 | 0
                                 1 | 1
                                 0 |

                  => 5 = reverse(101) = 101 in binary

Let's apply that to this part:

11*16^0 + 10*16^1 

First of all, for the first 4 (because 16^1 = 2^4 ) divisions, the remainder of division by 2 will only depend on 11 , because 16 % 2 == 0 .

11 | 1
5  | 1
2  | 0
1  | 1
0  |

So the last part of our number in binary will be:

1011

By the time we've done this, we will have gotten rid of the 16^1 , since we've done 4 divisions so far. So now we only depend on 10 :

10 | 0
 5 | 1
 2 | 0
 1 | 1
 0 |

So our final result will be:

10101011

Which is what we got with the classic approach!

As we can notice, we only need to convert the digits to binary individually, because they are what will, individually and sequentially, affect the result:

A = 10 = 1010
B = 11 = 1011

=> AB in binary = 10101011

For your base 2^k , do the same: convert each individual digit to binary, from most significant to least, and concatenate the results in order.

Example implementation:

def to_binary(number, k):
    result = []
    for x in number:
        # convert x to binary
        binary_x = []
        t = x
        while t != 0:
            binary_x.append(t % 2)
            t //= 2
        result.extend(binary_x[::-1])

    return result

#10 and 11 are digits here, so this is like AB.
print(to_binary([10, 11], 2**4))
print(to_binary([101, 51, 89], 2**7))

Prints:

[1, 0, 1, 0, 1, 0, 1, 1]
[1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1]

Note: there is actually a bug in the above code. For example, 2 in base 2**7 will get converted to 10 in binary. But digits in base 2**7 should have 7 bits, so you need to pad it to that many bits: 0000010 . I'll leave this as an exercise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM