简体   繁体   中英

How to convert a string representing a binary fraction to a number in Python

Let us suppose that we have a string representing a binary fraction such as:

".1"

As a decimal number this is 0.5. Is there a standard way in Python to go from such strings to a number type (whether it is binary or decimal is not strictly important).

For an integer, the solution is straightforward:

int("101", 2)
>>>5

int() takes an optional second argument to provide the base, but float() does not.

I am looking for something functionally equivalent (I think) to this:

def frac_bin_str_to_float(num):
    """Assuming num to be a string representing
    the fractional part of a binary number with
    no integer part, return num as a float."""
    result = 0
    ex = 2.0
    for c in num:
        if c == '1':
            result += 1/ex 
        ex *= 2
    return result

I think that does what I want, although I may well have missed some edge cases.

Is there a built-in or standard method of doing this in Python?

The following is a shorter way to express the same algorithm:

def parse_bin(s):
    return int(s[1:], 2) / 2.**(len(s) - 1)

It assumes that the string starts with the dot. If you want something more general, the following will handle both the integer and the fractional parts:

def parse_bin(s):
    t = s.split('.')
    return int(t[0], 2) + int(t[1], 2) / 2.**len(t[1])

For example:

In [56]: parse_bin('10.11')
Out[56]: 2.75

It is reasonable to suppress the point instead of splitting on it, as follows. This bin2float function (unlike parse_bin in previous answer) correctly deals with inputs without points (except for returning an integer instead of a float in that case).

For example, the invocations bin2float('101101') , bin2float('.11101') , and bin2float('101101.11101')` return 45, 0.90625, 45.90625 respectively.

def bin2float (b):
    s, f = b.find('.')+1, int(b.replace('.',''), 2)
    return f/2.**(len(b)-s) if s else f

You could actually generalize James's code to convert it from any number system if you replace the hard coded '2' to that base.

def str2float(s, base=10):
    dot, f = s.find('.') + 1, int(s.replace('.', ''), base)
    return f / float(base)**(len(s) - dot) if dot else f

You can use the Binary fractions package. With this package you can convert binary-fraction strings into floats and vice-versa.

Example:

>>> from binary_fractions import Binary
>>> float(Binary("0.1"))
0.5
>>> str(Binary(0.5))
'0b0.1'

It has many more helper functions to manipulate binary strings such as: shift, add, fill, to_exponential, invert...

PS: Shameless plug, I'm the author of this package.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM