Let's say I have some 32-bit numbers and some 64-bit numbers:
>>> import numpy as np
>>> w = np.float32(2.4)
>>> x = np.float32(4.555555555555555)
>>> y = np.float64(2.4)
>>> z = np.float64(4.555555555555555)
I can print them out with %f but it has extra, unneeded decimals:
>>> '%f %f %f %f' % (w, x, y, z)
'2.400000 4.555555 2.400000 4.555556'
I can use %g but it seems to have a small default precision:
>>> '%g %g %g %g' % (w, x, y, z)
'2.4 4.55556 2.4 4.55556'
I was thinking I should use something like .7 for 32-bit values and .15 for 64-bit values:
>>> '%.7g %.7g %.15g %.15g' % (w, x, y, z)
'2.4 4.555555 2.4 4.55555555555556'
This seems to work reasonably well, but the precision number is also used up for numbers in front of the decimal place too, e.g. 34567.375768.
In summary, what is the correct way to serialize floating-point values to text such that it preserves appropriate precision for 32-bit and 64-bit values but doesn't use any unnecessary space?
Update:
Examples of what I think the output should be:
number float32 float64
5 5 5
0.1 0.1 0.1
2.4 2.4 2.4
4.555555555555555 4.5555553 4.5555555555555554
12345678.92345678635 12345679.0 12345678.923456786
What I get with .7/.16. This actually looks okay:
>>> v32 = np.array([5, 0.1, 2.4, 4.555555555555555, 12345678.92345678635], dtype=np.float32)
>>> v64 = np.array([5, 0.1, 2.4, 4.555555555555555, 12345678.92345678635], dtype=np.float64)
>>> ('%.7g ' * len(v32)) % tuple(v32)
'5 0.1 2.4 4.555555 1.234568e+07 '
>>> ('%.16g ' * len(v64)) % tuple(v64)
'5 0.1 2.4 4.555555555555555 12345678.92345679 '
解决方案
You could try to use the np.finfo function to get the precision corresponding to your float
finfo32 = np.finfo(np.float32)
finfo64 = np.finfo(np.float64)
finfo32.resolution = 1e-6
finfo64.resolution = 1e-15
Now that you know how many decimals you want, say, 6, just use a rstrip("0") to get rid of the unnecessary 0s:
print ("%.6f" % your_float).strip("0")
If you're leaning towards %g, perhaps you may want to use a dynamic format such as:
>>> strf = lambda v: ("%%.%ig" % max(np.ceil(np.log10(v)), 7)) % v
>>> strf(123.456789)
'123.45679'
>>> strf(123456789.12345)
'123456789'