classification
Title: String format documentation contains error regarding %g
Type: behavior Stage:
Components: Documentation Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: Christian.Iversen, docs@python, eric.araujo, eric.smith, mark.dickinson, terry.reedy
Priority: normal Keywords:

Created on 2011-11-19 13:01 by Christian.Iversen, last changed 2011-11-26 09:17 by Christian.Iversen.

Messages (8)
msg147940 - (view) Author: Christian Iversen (Christian.Iversen) Date: 2011-11-19 13:01
The documentation for string format options state that both %f, %g and %e default to 6 digits after the decimal point. In fact, %g always seems to use 5 digits by default:

>>> "%g" % 2.1234567
'2.12346'
>>> "%f" % 2.1234567
'2.123457'
>>> "%e" % 2.1234567
'2.123457e+00'

But something much more insidious is wrong, because even when explicitly told how many digits to have, %g is one off:

>>> "%.6g" % 2.1234567
'2.12346'
>>> "%.6f" % 2.1234567
'2.123457'
>>> "%.6e" % 2.1234567
'2.123457e+00'

This can't be right?
msg147942 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2011-11-19 13:26
Yep, there's an oddity here that's directly inherited from C's sprintf family of functions, namely that in %e-style formatting you give the number of digits after the point (= one less than the total number of significant digits), and in %g-style formatting you give the total number of significant digits instead.

Can you give a pointer, or link, to the documentation section you were looking at?

The description at:

http://docs.python.org/library/stdtypes.html#string-formatting-operations

looks fine to me.  Note 3, which relates to the '%e' and '%f'-style formatting, talks about number of places after the point.  Note 4, which relates to '%g' formatting, talks about the total number of significant digits.
msg147943 - (view) Author: Christian Iversen (Christian.Iversen) Date: 2011-11-19 13:31
That was exactly the page I was looking at, and after some discussion on #python, I can see how they differ.

Perhaps this could be clarified in the documentation? It's very easy to miss as it is now. Maybe a note describing that %g is different from the others in this regard?
msg147946 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2011-11-19 14:05
> Maybe a note describing that %g is different from the others in this regard?

-1 from me;  I don't really see that that would improve the documentation.  Maybe that's just me, but I expect reference documentation to be clean, and uncluttered with too many warnings.  All the necessary information is already there, and adding extra notes like this just increases the total number of words to be read without adding new information.

In a tutorial, that would be different ... :-)

Leaving this open---others may have different takes on this.
msg147985 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2011-11-20 12:12
I agree with Mark.  The Documenting Python docs were recently updated by Raymond Hettinger to recommend not abusing notes and warnings, and the doc maintainer Georg Brandl approved it: d5d91b14b238 (#12047).
msg148032 - (view) Author: Christian Iversen (Christian.Iversen) Date: 2011-11-21 10:03
Certainly, I don't think we should be peppering the docs with warnings and notes, either.

However, the elements in question _already have_ notes. I propose that the note for %g (4) simply be updated for clarity. Something like this, perhaps:

"""Unlike the other floating-point formats, the precision determines the number of significant digits before and after the decimal point and defaults to 6."""

Simply adding "Unlike the other floating-point formats," at the beginning of the second line makes it much clearer that this is a different beast.

If you feel that is not the right solution, then feel free to close this issue.
msg148370 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2011-11-26 00:08
I find the doc for g/G less than clear.

1. (main entry) "Uses lowercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise."

'not less' means 'equal or greater', which to me is clearer. Even better and clearer to me would be "Uses decimal format if -4 <= exponent < precision, exponential format otherwise."


2. (note 4) "The precision determines the number of significant digits before and after the decimal point and defaults to 6."

>>> format(.001, 'g')
'0.001'

I only count 4, not 6.

Whoops, that is sort of documented, but in a really backwards way, by saying what the alternate form is. "The alternate form ... trailing zeroes are not removed as they would otherwise be."

>>> format(.001, '.3g')
'0.001'

Now I count 4, not 3.

3. (several notes) 'The alternate form'? I initially though this meant one of the two forms for g/G but then saw it used for other formats with just one form. It took too much searching to find the entry for '#', which I had never noticed before. Please expand to "The alternate '#' form" or add "(Alternate forms are selected by the '#' flag.)" after "Notes:".

I agree with C.I. that we could give some subtle emphasis that g/G treat precision differently. But the difference is more than just including the minimum 1 char before the decimal point in the precision.

>>> format(.001, 'f')
'0.001000'
msg148385 - (view) Author: Christian Iversen (Christian.Iversen) Date: 2011-11-26 09:17
Terry, the %g format always trims trailing zeroes, so you'd have to try with a number that doesn't end in zero.

I had to make a re-implementation of format for javascript:

http://paste.pocoo.org/show/513078/

If you look at the %g case, you can clearly see how much more complex and different it is, not that that itself indicates a bug. But it is different for sure :)
History
Date User Action Args
2011-11-26 09:17:00Christian.Iversensetmessages: + msg148385
2011-11-26 00:08:47terry.reedysetnosy: + terry.reedy
messages: + msg148370
2011-11-21 10:03:04Christian.Iversensetmessages: + msg148032
2011-11-20 12:12:53eric.araujosetnosy: + eric.araujo
messages: + msg147985
2011-11-19 18:35:09mark.dickinsonsetversions: + Python 3.2, Python 3.3, - Python 2.6
2011-11-19 18:24:51eric.smithsetnosy: + eric.smith
2011-11-19 14:05:22mark.dickinsonsetmessages: + msg147946
2011-11-19 13:31:16Christian.Iversensetmessages: + msg147943
2011-11-19 13:26:23mark.dickinsonsetnosy: + mark.dickinson
messages: + msg147942
2011-11-19 13:01:31Christian.Iversencreate