Micropython math weirdness

Hi,

I’m troubleshooting button input problem; the following code:
print(math.log2(16384))
print(int(math.log2(16384)))
print(math.log2(32768))
print(int(math.log2(32768)))

produces the following output:
14.0
14
15.0
14

Can anybody tell me why the log2(32768) is not being correctly converted to an int?

Cheers,
Stu

My guess would be that int() just truncates the floating point value, i.e. drops anything after the decimal place.

It could be that math.log2(32768) returns a value slightly less than 15.0 but when printed it comes out as 15.0.

Floating points are tricky - you could try rounding the number prior to converting it to an integer but it might not do anything?

This code snippet:

import math
v = math.log2(32768)
print(v)
print("{:.10f}".format(v))
print("{:.10f}".format(round(v)))
print(int(round(v)))

Outputs:

15.0
14.9999990463
15.0000000000
15

And seems to confirm what I suspected.

Same thing in CircuitPython, you’ve got round() if that works for you:

Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit Feather nRF52840 Express with nRF52840
>>> print(math.log(32768, 2))
15.0
>>> print(int(math.log(32768, 2)))
14
>>> print(round(math.log(32768, 2)))
15

There are often issues like this relating to the finite precision and the underlying representation of floating-point values but some MicroPythons will also suffer from bias in the internal rounding depending on how they store FP internally, see Adafruit Forums: CircuitPython floating point accuracy looks poor for 32bit.

Thanks ya’ll. I suspected as much, and I’m intrigued by the fact that the same code produces correct results on a MacBook.

Ended up removing the use of log2() to keep it nice and integral.
Happy weekends!