开发者

How to convert floating point number to base 3 in python

How does one convert a base-10 floating point number in Python to a base-N floating point number?

Specifically in my case, I would like t开发者_C百科o convert numbers to base 3 (obtain the representation of floating point numbers in base 3), for calculations with the Cantor set.


After a bit of fiddling, here's what I came up with. I present it to you humbly, keeping in mind Ignacio's warning. Please let me know if you find any flaws. Among other things, I have no reason to believe that the precision argument provides anything more than a vague assurance that the first precision digits are pretty close to correct.

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

These are iterators returning ints. Let me know if you need string conversion; but I imagine you can handle that.

EDIT: Actually looking at this some more, it seems like a if x == 0: break line after the yield in base3fraction gives you pretty much arbitrary precision. I went ahead and added that. Still, I'm leaving in the precision argument; it makes sense to be able to limit that quantity.

Also, if you want to convert back to decimal fractions, this is what I used to test the above.

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

Update

For some reason I've felt inspired by this problem. Here's a much more generalized solution. This returns two generators that generate sequences of integers representing the integral and fractional part of a given number in an arbitrary base. Note that this only returns two generators to distinguish between the parts of the number; the algorithm for generating digits is the same in both cases.

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)


Although 8 years have passed, I think it is worthwhile to mention a more compact solution.

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

For example calling the function to convert the number 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


You may try this solution to convert a float string to a given base.

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜