11

I am trying to make a decimal number ternary in a python function. My idea was to keep dividing until the quotient and remainder were equal, but I can't seem to get that to work. Here's my code:

l = 1


#problem code
def ternary(n):
    e = n/3
    q = n%3
    e= n/3
    q= e%3
    print q

r = input("What number should I convert?: ")
k = bin(r)
v = hex(r)
i = oct(r)
print k+"(Binary)"
print v+"(Hex)"
print i+"(Octals)"
ternary(r)
l+=1
# Variables:
#l,r,k,v,i 
#n,q,e
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Sidsy
  • 161
  • 2
  • 3
  • 11

4 Answers4

19

My idea was to keep dividing until the quotient and remainder were equal, but I can't seem to get that to work.

Yeah, something like that. Essentially, you want to keep dividing by 3, and collect the remainders. The remainders then make up the final number. In Python, you can use divmod to divide and collect the remainder.

def ternary (n):
    if n == 0:
        return '0'
    nums = []
    while n:
        n, r = divmod(n, 3)
        nums.append(str(r))
    return ''.join(reversed(nums))

Examples:

>>> ternary(0)
'0'
>>> ternary(1)
'1'
>>> ternary(2)
'2'
>>> ternary(3)
'10'
>>> ternary(12)
'110'
>>> ternary(22)
'211'
poke
  • 369,085
  • 72
  • 557
  • 602
  • If I wanted to write "(ternary)" next to it, would I make the final line(minus return) a variable and add the string"(Ternary)" to it, then return that? – Sidsy Jan 01 '16 at 20:39
  • Yeah that would work, but you could also just add a `+ ' (ternary)'` directly at the end of the `return` line. – poke Jan 01 '16 at 20:43
  • nums can be a string. You can achieve this with nums = str(r) + o and return o – Harrison Howard Aug 22 '21 at 04:46
  • 1
    @ForbiddenDuck When concatenating dynamic strings, [using `str.join()` is preferred](https://docs.python.org/3/faq/programming.html#what-is-the-most-efficient-way-to-concatenate-many-strings-together) over simply adding the strings since the latter will create multiple temporary string objects. – poke Aug 22 '21 at 13:17
15

You can also use the implementation of NumPy: https://numpy.org/doc/stable/reference/generated/numpy.base_repr.html?highlight=base_repr#numpy.base_repr

Though, I agree that a function for ternary exclusively is faster.

import numpy as np

number=100 # decimal
ternary=np.base_repr(number,base=3)
print(ternary)
#10201
SzorgosDiák
  • 181
  • 1
  • 4
  • 1
    Thank you for this code snippet, which might provide some limited short-term help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its long-term value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Toby Speight Aug 28 '19 at 16:49
  • Is this faster than other ways of doing it? – The Zach Man Dec 17 '19 at 21:02
10

This can also be done with recursion.

def ternary(n):
    e = n//3
    q = n%3
    if n == 0:
        return '0'
    elif e == 0:
        return str(q)
    else:
        return ternary(e) + str(q)

More generally, you can convert to any base b (where 2<=b<=10) with the following recursive function.

def baseb(n, b):
    e = n//b
    q = n%b
    if n == 0:
        return '0'
    elif e == 0:
        return str(q)
    else:
        return baseb(e, b) + str(q)
Chris Mueller
  • 6,490
  • 5
  • 29
  • 35
0

Here is a nonrecursive solution. It returns a little-endian array of integers, and it works for any natural numbered value and any natural numbered base≥2.

def base(b,n):
    size = math.ceil(math.log(max(1,n),b))
    return [place
        for i in range(size,-1,-1)
        if (place := n//b**i%b) or i<size] or [0]

The last if statement can be omitted if you don't mind the occasional zero padded answer such as [0,1,0,0,0].

Here is an example of its usage:

>>>base(3,7)
[2,1]

Here is its inverse:

def debase(b,x):
    return sum([xi*b**i 
        for i,xi in enumerate(reversed(x))])

And here is a test for its behavior:

assert all([
    debase(b,base(b,n))==n
    for b in range(2,16+1)
    for n in range(0,1024+1)])
16807
  • 1,418
  • 2
  • 18
  • 32