2

I am trying to write a program to convert a base 10 (decimal) number into a base 4 number. Here is the code I have come up with:

def decimal_to_base4(num):
    while num > 0:
        quotient = num//4
        base4 = num%4
        num = quotient
        print(base4, end="")
decimal_to_base4()

This code works fine, except for one problem:

For example, if my parameter value is 45, the output becomes 132. However since the base-4 value of 45 is 231, I want that output to be reversed to 231. How can I do that? I am having difficulties joining the integer outputs from the while loop, and reversing the same.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
abruzzi26
  • 159
  • 1
  • 10
  • You're just printing it in the wrong order. Consider storing it the digits in a list and printing the list in reverse. – adarsh Apr 10 '15 at 21:06

5 Answers5

1

You can use a list to store your result then print the list in reverse order

def decimal_to_base4(num):
    base4_ = []
    while num > 0:
        quotient = num//4
        base4 = num%4
        num = quotient
        base4_.append(str(base4))
    base4_ = "".join(base4_)
    print base4_[::-1]
decimal_to_base4(45)
avinash pandey
  • 1,321
  • 2
  • 11
  • 15
1

You could build the integer one digit at a time, then print it:

def decimal_to_base4(num):
    result=""
    while num > 0:
        quotient = num//4
        result+=str(num%4)
        num = quotient
    result = result[::-1]
    print(result, end="")
KSFT
  • 1,774
  • 11
  • 17
  • Thanks for the simply modified code. I don't understand one part of it: why have you included the 'result' accumulator? I would appreciate if you could explain the purpose of the result variable. Also, according to what I have learnt, I would initialize this to 0. Why have you initialized it to ""? – abruzzi26 Apr 11 '15 at 12:02
  • @abruzzi26 Which part don't you understand? – KSFT Apr 11 '15 at 12:05
  • If you look at my code, I have included the print statement within the while loop. Why is yours outside the loop? Secondly, what is the purpose of the 'result' variable which acts as an accumulator? – abruzzi26 Apr 11 '15 at 12:09
  • That's the point of my answer. I'm building up the result, then reversing it, then printing it. – KSFT Apr 11 '15 at 12:10
  • One more thing: why is the result variable initialized to "", and not 0? – abruzzi26 Apr 11 '15 at 12:11
  • It's initialized to `""`, which is the empty string. Each digit is converted to a string so they can be added to `result`. It's a string so that you can reverse it; you can't reverse an int. – KSFT Apr 11 '15 at 12:14
1

The easiest way to convert the number into base 4 is to first convert the number into hexadecimal (base 16) using Python's built-in facilities, then map each hex digit to two base-4 digits. Since each base-4 digit represents 2 bits, and each base-16 digit represents 4 bits, this is an exact mapping.

DIGIT_MAP = {"0": "00", "1": "01", "2": "02", "3": "03",
             "4": "10", "5": "11", "6": "12", "7": "13",
             "8": "20", "9": "21", "a": "22", "b": "23",
             "c": "30", "d": "31", "e": "32", "f": "33"}

def decimal_to_base4(num):
    return "".join(DIGIT_MAP[c] for c in "%x" % num).lstrip("0") or "0"

How it works:

  • First, we convert the incoming number to hex using "%x" % num. We could also use hex(), but this adds a leading 0x to the conversion, which we'd then have to strip off (i.e. this could also be written as hex(num)[2:]).

  • We loop over the result, setting c to each character in the hex version of the number.

  • For each iteration in the loop, we yield DIGIT_MAP[c], which is the two base-4 digits that are equivalent to the given base-16 digit.

  • We join the resulting strings with the null string, resulting in a single string with all the numbers in order.

  • The result may have a leading zero since any hex digit less than 4 results in a base-4 digit-pair starting with 0. So we strip this off using .lstrip("0").

  • But if the number was zero to begin with, the .lstrip() takes off the entire digit, resulting in an empty string, "". The or "0" restores the "0" in the case of an empty string.

kindall
  • 178,883
  • 35
  • 278
  • 309
0

Recursive solution:

def decimal_to_base4(num):
    if num < 4:
        return str(num)
    return decimal_to_base4(num // 4) + str(num % 4)

This works in the same way as the one you have, except that it solves your problem by appending the mod part to the string after the recursive call returns. So if you did the append in the reverse order, you are back to the same problem again

smac89
  • 39,374
  • 15
  • 132
  • 179
  • Thanks for the explanation. I don't quite understand the purpose of the **return** function in this code. Could you please help me understand this? – abruzzi26 Apr 11 '15 at 12:20
  • @abruzzi26 There are 2 return statements which one is confusing you? – smac89 Apr 11 '15 at 16:53
0

It is also possible to use a recursive approach such as

import sys

def decimal_to_base4(num):
    if num == 0:
       return
    quotient = num//4
    base4 = num%4
    num = quotient
    decimal_to_base4(num)
    sys.stdout.write(str(base4))

decimal_to_base4(45)