Skip to content

brainhops._core.numeric

Helpers for numbers as files store them.

Many file formats store numbers in single precision, sometimes in another unit than the one brainhops uses (milliseconds instead of seconds, radians instead of degrees). Converted to double precision, such a number reads as 0.30000001192092896 rather than as the 0.3 that was written. The functions of this module recover the short decimal that was meant.

Functions:

shortest_decimal

shortest_decimal(
    value: float,
    encode: Callable[[float], float] | None = None,
) -> float

Find the shortest decimal that a file stores as the same single precision number as value.

A writer stores a value d as the single-precision number float32(encode(d)), where encode converts the value into the unit of the file. A reader that decodes that number in double precision obtains value, which is close to the number that was written, but rarely equal to it. This function returns the decimal with the fewest significant digits that the writer would store as the same number. That decimal is the value the reader reports: it reads back exactly as it was written, and writing it again stores the same bits.

With the identity as encode, this is the question that the shortest round-trip representation of a single-precision number answers, and the result is the value that str(numpy.float32(value)) prints.

Parameters:

Name Type Description Default
value float

The decoded value, in double precision.

required
encode callable

The function that converts a value into what the file stores, before the rounding to single precision. By default, the identity.

None

Returns:

Type Description
float

The shortest decimal that is stored as the same number. A value that is zero or not finite is returned as it is.

Examples:

>>> import math
>>> import numpy as np
>>> shortest_decimal(float(np.float32(0.3)))
0.3
>>> stored = np.float32(2000.7)  # a repetition time, in milliseconds
>>> float(stored) * 1e-3
2.000699951171875
>>> shortest_decimal(float(stored) * 1e-3, lambda s: s / 1e-3)
2.0007
>>> radians = np.float32(math.radians(9))  # a flip angle
>>> math.degrees(float(radians))
9.000000250447817
>>> shortest_decimal(math.degrees(float(radians)), math.radians)
9.0

float32_repr

float32_repr(value: Any) -> float

The shortest decimal that is stored as the same single-precision number as value.

Parameters:

Name Type Description Default
value float

A number, usually one read from a single-precision slot.

required

Returns:

Type Description
float

The shortest decimal with the same single-precision value, such as 0.3 for the single-precision number 0.30000001192092896.