Let a be a special float64:
In [26]: a = np.float64.fromhex('-1p-97')
In [27]: a
Out[27]: -6.310887241768095e-30
It has uniquestra, a shortest decimal string that uniquely identifies it (thus can be eval-ed to reproduce it exactly):
In [33]: uniquestra = np.format_float_scientific(a, unique=True)
In [34]: uniquestra
Out[34]: '-6.310887241768095e-30'
In [35]: eval(uniquestra)==a
Out[35]: True
Because a is a special float, unlike most other floats, it has a correctly-rounded precision=15 decimal string that is different from uniquestra:
In [36]: roundedstra = np.format_float_scientific(a, unique=False, precision=15)
In [37]: roundedstra
Out[37]: '-6.310887241768094e-30'
In [38]: eval(roundedstra)==a
Out[38]: False
So far, so good. This kind of thing is why format_float_scientific has the unique flag, to choose between these two cases depending on which is needed in a given situation.
The problem comes with array2string, who takes a floatmode=unique option that should give uniquestr and instead gives roundedstr. The problem is that internally array2string uses FloatingFormat which in floatmode='unique' mode effectively uses format_float_scientific twice: Once with unique=True, precision=None to figure out how many digits of precision are enough to uniquely represent the float, and then a second time with unique=False, precision=foo to actually do the formatting. Most of the time this correctly gives a unique representation of the float, but for a special float like a it fails and gives roundedstra instead of uniquestra.
Reproducing code example:
import numpy as np
a = np.float64.fromhex('-1p-97')
assert eval(np.array2string(a, floatmode='unique'))==a
NumPy/Python version information:
1.20.1 3.8.8 (default, Feb 24 2021, 13:46:16)
[Clang 10.0.0 ]
Let
abe a special float64:It has
uniquestra, a shortest decimal string that uniquely identifies it (thus can be eval-ed to reproduce it exactly):Because
ais a special float, unlike most other floats, it has a correctly-rounded precision=15 decimal string that is different fromuniquestra:So far, so good. This kind of thing is why
format_float_scientifichas theuniqueflag, to choose between these two cases depending on which is needed in a given situation.The problem comes with
array2string, who takes afloatmode=uniqueoption that should giveuniquestrand instead givesroundedstr. The problem is that internallyarray2stringusesFloatingFormatwhich infloatmode='unique'mode effectively uses format_float_scientific twice: Once withunique=True, precision=Noneto figure out how many digits of precision are enough to uniquely represent the float, and then a second time withunique=False, precision=footo actually do the formatting. Most of the time this correctly gives a unique representation of the float, but for a special float likeait fails and givesroundedstrainstead ofuniquestra.Reproducing code example:
NumPy/Python version information: