1

I want to use the packages bitstring and mpmath (or any other way to guarantee an arbitrarily set output precision and specified rounding mode) to calculate values of rcp, sqrt, sin, cos, ln, exp,... on float inputs given as binary bitstrings and get a binary bitstring answer.

My go-to for this is MPFR in C, but I want to explore Python's floating point high-precision packages, hoping for easier handling. My first problem is how to reverse the following decimal float to bitstring conversion:

>>> from bitstring import *
>>> a = BitArray(float=1.2,length=32)
>>> a.bin
'00111111100110011001100110011010'

i.e. how to feed '00111111100110011001100110011010' to either bitstring or mpmath in a way that it interprets it as (just over) 1.2 and then feed that to a function such as sin, cos, or ln (turning my answer into a bitstring again).

I'm finding it hard to learn about binary input from the Python bitstring/mpmath documentation. It only says about the difficulties of decimal float representation, but not how to bypass these simply inputting exact binary floats.

martineau
  • 119,623
  • 25
  • 170
  • 301

2 Answers2

2

According to BitArray doc string, you can specify bin argument:

__init__(self, auto=None, length=None, offset=None, **kwargs)
    Either specify an 'auto' initialiser:
    auto -- a string of comma separated tokens, an integer, a file object,
            a bytearray, a boolean iterable or another bitstring.

    Or initialise via **kwargs with one (and only one) of:
    bytes -- raw data as a string, for example read from a binary file.
    bin -- binary string representation, e.g. '0b001010'.   <--------------
    hex -- hexadecimal string representation, e.g. '0x2ef'
    oct -- octal string representation, e.g. '0o777'.
    uint -- an unsigned integer.
    int -- a signed integer.
    float -- a floating point number.
    uintbe -- an unsigned big-endian whole byte integer.
    intbe -- a signed big-endian whole byte integer.
    floatbe - a big-endian floating point number.
    uintle -- an unsigned little-endian whole byte integer.
    intle -- a signed little-endian whole byte integer.
    floatle -- a little-endian floating point number.
    uintne -- an unsigned native-endian whole byte integer.
    intne -- a signed native-endian whole byte integer.
    floatne -- a native-endian floating point number.
    se -- a signed exponential-Golomb code.
    ue -- an unsigned exponential-Golomb code.
    sie -- a signed interleaved exponential-Golomb code.
    uie -- an unsigned interleaved exponential-Golomb code.
    bool -- a boolean (True or False).
    filename -- a file which will be opened in binary read-only mode.

    Other keyword arguments:
    length -- length of the bitstring in bits, if needed and appropriate.
              It must be supplied for all integer and float initialisers.
    offset -- bit offset to the data. These offset bits are
              ignored and this is intended for use when
              initialising using 'bytes' or 'filename'.

>>> a = BitArray(bin='00111111100110011001100110011010')
>>> a.bin
'00111111100110011001100110011010'

Use float property to get float value:

>>> a.float
1.2000000476837158
>>> 
falsetru
  • 357,413
  • 63
  • 732
  • 636
2

BitArray takes the bin parameter, which initialises it from a binary string representation:

>>> from bitstring import *
>>> a = BitArray(float=1.2, length=32)
>>> a.bin
'00111111100110011001100110011010'
>>> b = BitArray(bin=a.bin)
>>> b.float
1.2000000476837158

So a general function to do this:

def float_from_bitstring(bitstring):
    return BitArray(bin=bitstring).float
Artyer
  • 31,034
  • 3
  • 47
  • 75