如何在Python中将浮点数转换为三进制

8 投票
3 回答
6212 浏览
提问于 2025-04-16 12:29

怎样把Python中的十进制浮点数转换成N进制的浮点数呢?

具体来说,我想把数字转换成三进制(也就是得到三进制下的浮点数表示),这样可以用来进行一些关于康托集的计算。

3 个回答

0

你可以试试这个方法,把一个浮点数的字符串转换成指定的进制。

def eval_strint(s, base=2):
    assert type(s) is str
    assert 2 <= base <= 36
    ###
    ### YOUR CODE HERE
    ###
    return int(s,base)

def is_valid_strfrac(s, base=2):
    return all([is_valid_strdigit(c, base) for c in s if c != '.']) \
        and (len([c for c in s if c == '.']) <= 1)
    
def eval_strfrac(s, base=2):
assert is_valid_strfrac(s, base), "'{}' contains invalid digits for a base-{} number.".format(s, base)

stg = s.split(".")
float_point=0.0
if len(stg) > 1:
    float_point = (eval_strint(stg[1],base) * (base**(-len(stg[1]))))
stg_float = eval_strint(stg[0],base) + float_point
return stg_float
1

虽然已经过去了8年,但我觉得提到一个更简洁的解决方案还是很有意义的。

def baseConversion( x=1, base=3, decimals=2 ):
    import math
    n_digits = math.floor(-math.log(x, base))#-no. of digits in front of decimal point
    x_newBase = 0#initialize
    for i in range( n_digits, decimals+1 ):
        x_newBase = x_newBase + int(x*base**i) % base * 10**(-i)
    return x_newBase

比如说,调用这个函数来转换数字5+1/9+1/27。

def baseConversion( x=5+1/9+1/27, base=3, decimals=2 ) 
12.01
def baseConversion( x=5+1/9+1/27, base=3, decimals=3 ) 
12.011
7

经过一番折腾,我得出了这个结果。谨慎地呈现给你们,同时也记住了Ignacio的警告。如果你发现有什么问题,请告诉我。总之,我没有理由相信precision这个参数能提供比模糊的保证更多的东西,最多就是前precision位数字大致是正确的。

def base3int(x):
    x = int(x)
    exponents = range(int(math.log(x, 3)), -1, -1)
    for e in exponents:
        d = int(x // (3 ** e))
        x -= d * (3 ** e)
        yield d

def base3fraction(x, precision=1000):
    x = x - int(x)
    exponents = range(-1, (-precision - 1) * 2, -1)
    for e in exponents:
        d = int(x // (3 ** e))
        x -= d * (3 ** e)
        yield d
        if x == 0: break

这些是返回整数的迭代器。如果你需要把它们转换成字符串,告诉我一声;不过我想你应该能搞定这个。

补充说明:再仔细看看这个,发现其实在base3fraction中的yield后面加一行if x == 0: break,就能得到几乎任意精度的结果。我已经把这行加上了。不过,我还是保留了precision这个参数;限制这个数量是有意义的。

另外,如果你想把结果转换回十进制分数,这就是我用来测试上面内容的代码。

sum(d * (3 ** (-i - 1)) for i, d in enumerate(base3fraction(x)))

更新

不知道为什么,这个问题让我感到很有灵感。这里有一个更通用的解决方案。它返回两个生成器,生成表示给定数字在任意进制下的整数部分和小数部分的整数序列。请注意,这里只返回两个生成器,用来区分数字的不同部分;生成数字的算法在两种情况下是一样的。

def convert_base(x, base=3, precision=None):
    length_of_int = int(math.log(x, base))
    iexps = range(length_of_int, -1, -1)
    if precision == None: fexps = itertools.count(-1, -1)
    else: fexps = range(-1, -int(precision + 1), -1)

    def cbgen(x, base, exponents):
        for e in exponents:
            d = int(x // (base ** e))
            x -= d * (base ** e)
            yield d
            if x == 0 and e < 0: break

    return cbgen(int(x), base, iexps), cbgen(x - int(x), base, fexps)

撰写回答