在Python中将十进制转换为三进制(基数为3)

11

我正在尝试在Python函数中将一个十进制数转换为三进制。我的想法是不断除以3直到商和余数相等,但似乎无法实现。以下是我的代码:

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

你能修正一下缩进吗? - Iron Fist
1
你的函数计算了 eq 两次。这是有意为之吗? - Martijn Pieters
在这里使用divmod功能,就像to_base函数一样 https://dev59.com/UJHea4cB1Zd3GeqPmTuc#33802414 - Padraic Cunningham
@Padraic Cunningham,你能举个例子说明它是如何工作的以及如何使用它吗? - Sidsy
@Sidsy,to_base(123, 3) 将为您提供123的3进制,即'11120',只需应用相同的逻辑即可。 - Padraic Cunningham
显示剩余2条评论
4个回答

19

我的想法是一直除下去,直到商和余数相等,但似乎行不通。

对,就像这样。本质上,你想要一直除以3,并收集余数。然后这些余数组成最终的数字。在Python中,你可以使用divmod来执行除法并收集余数。

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

示例:

>>> ternary(0)
'0'
>>> ternary(1)
'1'
>>> ternary(2)
'2'
>>> ternary(3)
'10'
>>> ternary(12)
'110'
>>> ternary(22)
'211'

如果我想在旁边写上“(三元)”,我应该将最后一行(不包括return)变成一个变量,并在其后添加字符串“(Ternary)”,然后返回它吗? - Sidsy
没错,那也可以,但你也可以直接在return行的末尾添加 + '(三元运算符)'. - poke
nums 可以是字符串。你可以通过 nums = str(r) + o 来实现这一点,并返回 o。 - Harrison Howard
1
@ForbiddenDuck 当连接动态字符串时,最好使用str.join()而不是简单地添加字符串,因为后者会创建多个临时字符串对象。请参考:https://docs.python.org/3/faq/programming.html#what-is-the-most-efficient-way-to-concatenate-many-strings-together - poke

15

1
感谢您提供这段代码片段,它可能会在短期内提供一些有限的帮助。通过展示为什么这是一个好的解决方案,适当的解释将极大地提高其长期价值,并使其对未来具有类似问题的读者更有用。请编辑您的答案以添加一些解释,包括您所做的假设。 - Toby Speight
这种方式比其他方式更快吗? - The Zach Man

10
这也可以通过递归来实现。
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)

更一般地,您可以使用以下递归函数将任何数字转换为任意基数b(其中2<=b<=10)。
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)

0
这里提供了一种非递归解决方案。它返回一个小端整数数组,并且适用于任何自然数值和任何自然数基数≥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]

如果你不介意偶尔出现类似 [0,1,0,0,0] 这样的零填充答案,那么最后一个 if 语句可以省略。

以下是其使用示例:

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

这是它的反向:

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

这里是对其行为进行测试的代码:

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

现在好多了,尽管例如对于 base(2, 2251799813685247) 你确实会产生一个前导零。(那个数字是2的51次方减1。) - Kelly Bundy
1
建议:先将 n//b**i%b 分割开。>0 不是必需的。 - Kelly Bundy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接