Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

32-bit floating point math in 64-bit Python [duplicate]

I program embedded software that runs 32-bit math in 32-bit hardware. I routinely investigate floating point imprecision issues.

In-target debugging is routine, but for convenience I'd like to be able to do quick calculations in my desktop Python environment, having it behave like the target, i.e, do the math in 32 bits.

The desktop hardware, the OS and the Python installation are 64-bit.

We're talking IEEE floats all around.

Ideally, after configuration, I'd like to be able to type, say, 0.1+0.2 at the Python interpreter and have it already know to process and store everything using 32-bit math.

What are my options?

like image 381
Emilio M Bumachar Avatar asked Feb 15 '16 12:02

Emilio M Bumachar


People also ask

Are Python floats 32 or 64-bit?

Python's floating-point numbers are usually 64-bit floating-point numbers, nearly equivalent to np. float64 . In some unusual situations it may be useful to use floating-point numbers with more precision.

What is the difference between a 32 bit and 64-bit floating point value?

Floating Point Numbers Floats generally come in two flavours: “single” and “double” precision. Single precision floats are 32-bits in length while “doubles” are 64-bits. Due to the finite size of floats, they cannot represent all of the real numbers - there are limitations on both their precision and range.

Is Double always 64 bits?

No, an IEEE 754 double-precision floating point number is always 64 bits. Similarly, a single-precision float is always 32 bits. If your question is about C# and/or .

How do you check if two floats are the same in Python?

How To Compare Floats in Python. If abs(a - b) is smaller than some percentage of the larger of a or b , then a is considered sufficiently close to b to be "equal" to b . This percentage is called the relative tolerance. You can specify the relative tolerance with the rel_tol keyword argument of math.


1 Answers

Extending Yann Vernier's idea, this would be a possible transformer that injects a numpy import and wraps every float literal in numpy.float32.

import ast

class Float32Visitor(ast.NodeTransformer):
    def visit_Module(self, node):
        # add numpy import
        imp = ast.Import([ast.alias("numpy")])
        node.body = [imp] + node.body
        return node

    def visit_Num(self, node):
        if not isinstance(node.n, float):
            return node

        return ast.Call(
            func=ast.Attribute(
                value=ast.Name(id="numpy", ctx=ast.Load()),
                attr="float32", ctx=ast.Load()
            ),
            args=[node],
            keywords=[],
            starargs=None,
            kwargs=None
        )

Hooking this into compile is a bit tricky and hackish, however. To do it for a single piece of code, you'd do something like this:

import ast
parsed = ast.parse(my_code, "my_code.py", mode="exec")
parsed = Float32Visitor().visit(parsed)
code = compile(parsed, "my_code.py", mode="exec")
my_code = eval(code)
like image 85
filmor Avatar answered Nov 15 '22 03:11

filmor