Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If you multiply the smallest positive floating point value by a non-zero number, are you guaranteed a non-zero result?

If I take epsilon to be the smallest positive non-zero floating point number (be it 16, 32, or 64 bit) and multiply epsilon by a non-zero floating point value of the same size:

Am I guaranteed a non-zero result of the same sign as the original value? Or do I risk rounding error (zero, or switching signs)?

Environment: Python/Numpy

like image 522
David Parks Avatar asked Jun 05 '17 17:06

David Parks


2 Answers

No.

In [1]: import numpy

In [2]: x = numpy.nextafter(0, 1)

In [3]: x
Out[3]: 4.9406564584124654e-324

In [4]: x*x
Out[4]: 0.0

When the exact result is between 0 and the smallest positive float, it has to round to one of those options, and in this case, 0 is closer.

If for some reason you want to customize this behavior, NumPy lets you customize the behavior of underflow and other IEEE 754 floating-point exceptions with numpy.seterr, although it won't affect operations on ordinary Python objects:

In [5]: numpy.seterr(under='raise')
Out[5]: {'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}

In [6]: x # NumPy float, not regular float, despite its looks
Out[6]: 4.9406564584124654e-324

In [7]: x*x
---------------------------------------------------------------------------
FloatingPointError                        Traceback (most recent call last)
<ipython-input-7-a3ff2a28c75d> in <module>()
----> 1 x*x

FloatingPointError: underflow encountered in double_scalars

In [8]: (4.9406564584124654e-324)**2 # regular float
Out[8]: 0.0

There's no way to change the rounding mode.

like image 197
user2357112 supports Monica Avatar answered Oct 07 '22 14:10

user2357112 supports Monica


Of course not, and epsilon has little to do with it. For example,

>>> x = 1e-200
>>> x
1e-200

is far from epsilon, but

>>> x * x
0.0

underflows to 0. If we actually used epsilon instead, then, e.g., multiplying it by 0.25 would underflow to 0 too.

Provided your platform C compiler and hardware support the 754 standard, though, the sign of the zero would match the sign of the multiplicand:

>>> x * -x
-0.0
like image 29
Tim Peters Avatar answered Oct 07 '22 15:10

Tim Peters