9

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 '
7
  • For me it is not really clear which output you desire. Could you provide us with the specific output you want to have? Commented Sep 18, 2012 at 21:19
  • I'd simply use strip('0') to remove trailing zeros. Commented Sep 18, 2012 at 21:19
  • What is wrong with "%.3f" % z -> '4.556', "%.3f" % q -> '2131234.556'? Commented Sep 18, 2012 at 21:20
  • 2
    How is '%.16g' (I think .16 is correct) not exactly what you need? Always 16 signficiant figures... You could also just use '%r' (representation) which is probably the same result. "used up in front" sounds like you have some misconception about floating points? Commented Sep 18, 2012 at 21:39
  • The precision number being also used up for numbers in front of the decimal point is a feature. Since those digits also take up room, they are just as important as those after the decimal place. When one speaks of significant 15 or 7 digits, the digit count always refers to the total number of digits. Commented Sep 18, 2012 at 21:51

2 Answers 2

8

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'
Sign up to request clarification or add additional context in comments.

5 Comments

updated question, I think %g does actually do what I want it to
@jterrace: I'm not sure about that, check the last entry of v32 with '%.7g'.
Seems strange that it's 1.234568e+07 instead of 1.234569e+07?
That's what %g does.. it uses %e if it's more efficient. I'm actually okay with scientific notation
Yeah, the example was what I thought the answer should be, but I guess %g is okay. Still not sure what precision I should be using to make sure I don't lose precision
2

I am not exactly sure what you are trying to accomplish. However, this might help. You wrote

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.

You can use %f instead of g. From the Python docs:

The precision is a decimal number indicating how many digits should be displayed after the decimal point for a floating point value formatted with 'f' and 'F', or before and after the decimal point for a floating point value formatted with 'g' or 'G'.

>>> z = np.float64(4.555555555555555)
>>> "%.3f" % z
'4.556'
>>> q = np.float64(2131234.555555555555555)
>>> "%.3f" % q
'2131234.556'
>>>

1 Comment

Then change the '3' to another value. I still don't entirely get what you want.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.