# Floating point "g" format not stripping trailing zeros Classic List Threaded 21 messages 12
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 According to the documentation of the "g" floating-point format, trailing zeros should be stripped from the resulting string: """ General format. For a given precision p >= 1, this rounds the number to p significant digits and then formats the result in either fixed-point format or in scientific notation, depending on its magnitude.[...] In both cases insignificant trailing zeros are removed from the significand, and the decimal point is also removed if there are no remaining digits following it. """ However, in some cases, the trailing zeros apparently remain: >>> from decimal import Decimal as D >>> x = D(1)/D(999) >>> '{:.15g}'.format(x) '0.00100100100100100' For floats, the trailing zeros are removed: >>> '{:.15g}'.format(1. / 999) '0.001001001001001' This behavior is present in both 2.7.8 and 3.4.1. Is this a bug in the formatting of Decimals?
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On 11/02/2015 20:02, Hrvoje Nik?i? wrote: > According to the documentation of the "g" floating-point format, > trailing zeros should be stripped from the resulting string: > > """ > General format. For a given precision p >= 1, this rounds the number > to p significant digits and then formats the result in either > fixed-point format or in scientific notation, depending on its > magnitude.[...] > In both cases insignificant trailing zeros are removed from the > significand, and the decimal point is also removed if there are no > remaining digits following it. > """ > > However, in some cases, the trailing zeros apparently remain: > >>>> from decimal import Decimal as D >>>> x = D(1)/D(999) >>>> '{:.15g}'.format(x) > '0.00100100100100100' > > For floats, the trailing zeros are removed: > >>>> '{:.15g}'.format(1. / 999) > '0.001001001001001' > > This behavior is present in both 2.7.8 and 3.4.1. Is this a bug in the > formatting of Decimals? > I'd say it's a bug.  P is 15, you've got 17 digits after the decimal place and two of those are insignificant trailing zeros. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On Wed, Feb 11, 2015 at 2:48 PM, Mark Lawrence wrote: > On 11/02/2015 20:02, Hrvoje Nik?i? wrote: >> >> According to the documentation of the "g" floating-point format, >> trailing zeros should be stripped from the resulting string: >> >> """ >> General format. For a given precision p >= 1, this rounds the number >> to p significant digits and then formats the result in either >> fixed-point format or in scientific notation, depending on its >> magnitude.[...] >> In both cases insignificant trailing zeros are removed from the >> significand, and the decimal point is also removed if there are no >> remaining digits following it. >> """ >> >> However, in some cases, the trailing zeros apparently remain: >> >>>>> from decimal import Decimal as D >>>>> x = D(1)/D(999) >>>>> '{:.15g}'.format(x) >> >> '0.00100100100100100' >> >> For floats, the trailing zeros are removed: >> >>>>> '{:.15g}'.format(1. / 999) >> >> '0.001001001001001' >> >> This behavior is present in both 2.7.8 and 3.4.1. Is this a bug in the >> formatting of Decimals? >> > > I'd say it's a bug.  P is 15, you've got 17 digits after the decimal place > and two of those are insignificant trailing zeros. Actually it's the float version that doesn't match the documentation. In the decimal version, sure there are 17 digits after the decimal place there, but the first two -- which are leading zeroes -- would not normally be considered significant. The float version OTOH is only giving you 13 significant digits when 15 were requested. For illustration, compare the same formatting with the scale ramped up to make it switch to exponential notation: >>> '{:.15g}'.format(D(1) / D(999000000)) '1.00100100100100e-9' >>> '{:.15g}'.format(1./999000000) '1.001001001001e-09'
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On Wed, Feb 11, 2015 at 3:19 PM, Ian Kelly wrote: > On Wed, Feb 11, 2015 at 2:48 PM, Mark Lawrence wrote: >> On 11/02/2015 20:02, Hrvoje Nik?i? wrote: >>> >>> According to the documentation of the "g" floating-point format, >>> trailing zeros should be stripped from the resulting string: >>> >>> """ >>> General format. For a given precision p >= 1, this rounds the number >>> to p significant digits and then formats the result in either >>> fixed-point format or in scientific notation, depending on its >>> magnitude.[...] >>> In both cases insignificant trailing zeros are removed from the >>> significand, and the decimal point is also removed if there are no >>> remaining digits following it. >>> """ >>> >>> However, in some cases, the trailing zeros apparently remain: >>> >>>>>> from decimal import Decimal as D >>>>>> x = D(1)/D(999) >>>>>> '{:.15g}'.format(x) >>> >>> '0.00100100100100100' >>> >>> For floats, the trailing zeros are removed: >>> >>>>>> '{:.15g}'.format(1. / 999) >>> >>> '0.001001001001001' >>> >>> This behavior is present in both 2.7.8 and 3.4.1. Is this a bug in the >>> formatting of Decimals? >>> >> >> I'd say it's a bug.  P is 15, you've got 17 digits after the decimal place >> and two of those are insignificant trailing zeros. > > Actually it's the float version that doesn't match the documentation. > In the decimal version, sure there are 17 digits after the decimal > place there, but the first two -- which are leading zeroes -- would > not normally be considered significant. The float version OTOH is only > giving you 13 significant digits when 15 were requested. > > For illustration, compare the same formatting with the scale ramped up > to make it switch to exponential notation: > >>>> '{:.15g}'.format(D(1) / D(999000000)) > '1.00100100100100e-9' >>>> '{:.15g}'.format(1./999000000) > '1.001001001001e-09' Although here's something else that is definitely an issue with the decimal formatting: >>> '{:.15g}'.format(D(1)/D(999000)) '0.00000100100100100100' This has an exponent of -6, so according to the docs it should be formatted in exponential notation.
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Hrvoje Nikšić-3 > >>>>> from decimal import Decimal as D > >>>>> x = D(1)/D(999) > >>>>> '{:.15g}'.format(x) > >> > >> '0.00100100100100100' [...] > > I'd say it's a bug.  P is 15, you've got 17 digits after the decimal place > > and two of those are insignificant trailing zeros. > > Actually it's the float version that doesn't match the documentation. > In the decimal version, sure there are 17 digits after the decimal > place there, but the first two -- which are leading zeroes -- would > not normally be considered significant. {:.15g} is supposed to give 15 digits of precision, but with trailing zeros removed.  For example, '{:.15g}'.format(Decimal('0.5')) should yield '0.5', not '0.500000000000000' -- and, it indeed does.  It is only for some numbers that trailing zeros are not removed, which looks like a bug.  The behavior of floats matches both the documentation and other languages using the 'g' decimal format, such as C. > The float version OTOH is only giving you 13 significant digits when > 15 were requested. It is giving 15 significant digits if you count the trailing zeros that have been removed.  If those two digits had not been zeros, they would have been included.  This is again analogous to '{:.15g}'.format(0.5) returning '0.5'.
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nik?i? wrote: >> >>>>> from decimal import Decimal as D >> >>>>> x = D(1)/D(999) >> >>>>> '{:.15g}'.format(x) >> >> >> >> '0.00100100100100100' > [...] >> > I'd say it's a bug.  P is 15, you've got 17 digits after the decimal place >> > and two of those are insignificant trailing zeros. >> >> Actually it's the float version that doesn't match the documentation. >> In the decimal version, sure there are 17 digits after the decimal >> place there, but the first two -- which are leading zeroes -- would >> not normally be considered significant. > > {:.15g} is supposed to give 15 digits of precision, but with trailing > zeros removed. The doc says with "insignificant" trailing zeros removed, not all trailing zeros. > For example, '{:.15g}'.format(Decimal('0.5')) should > yield '0.5', not '0.500000000000000' -- and, it indeed does.  It is > only for some numbers that trailing zeros are not removed, which looks > like a bug.  The behavior of floats matches both the documentation and > other languages using the 'g' decimal format, such as C. Ah, I see now what's going on here. With floats, there is really no notion of significant digits. The values 0.5 and 0.50000 are completely equivalent. With decimals, that's not exactly true; if you give the decimal a trailing zero then you are telling it that the zero is significant. >>> Decimal('0.5') Decimal('0.5') >>> Decimal('0.50000') Decimal('0.50000') >>> Decimal('0.5').as_tuple() DecimalTuple(sign=0, digits=(5,), exponent=-1) >>> Decimal('0.50000').as_tuple() DecimalTuple(sign=0, digits=(5, 0, 0, 0, 0), exponent=-5) These are distinct; the decimal knows how many significant digits you passed it. As a result, these are also distinct: >>> '{:.4g}'.format(Decimal('0.5')) '0.5' >>> '{:.4g}'.format(Decimal('0.50000')) '0.5000' Now what happens in your original example of 1/999? The default decimal context uses 28 digits of precision, so the result of that calculation will have 28 significant digits in it. >>> decimal.getcontext().prec 28 >>> Decimal(1) / Decimal(999) Decimal('0.001001001001001001001001001001') When you specify the a precision of 15 in your format string, you're telling it to take the first 15 of those. It doesn't care that the last couple of those are zeros, because as far as it's concerned, those digits are significant.
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Hrvoje Nikšić-3 Ian Kelly writes: > When you specify the a precision of 15 in your format string, you're > telling it to take the first 15 of those. It doesn't care that the > last couple of those are zeros, because as far as it's concerned, > those digits are significant. OK, it's a bit surprising, but also consistent with the rest of the decimal module. Thanks for clearing it up. My concrete use case is printing an arbitrary fraction as a user-readable decimal, rounded to the specified number of digits, and using the exponential notation where appropriate: import decimal _dec_fmt_context = decimal.Context(prec=15, rounding=decimal.ROUND_HALF_UP) def _format(frac):     with decimal.localcontext(_dec_fmt_context):         dec = decimal.Decimal(frac.numerator) / decimal.Decimal(frac.denominator)         return '{:g}'.format(dec) The decimal obtained by dividing the numerator with the denominator includes trailing zeros. Calling normalize() to get rid of them will have the unfortunate side effect of turning 9806650 into 9.80665e+6, and the method recommended in the documentation: def remove_exponent(d):     return d.quantize(decimal.Decimal(1)) if d == d.to_integral() else d.normalize() ...will raise "decimal.InvalidOperation: quantize result has too many digits for current context" when the number is too large. For now I'm emulating the behavior of '%g' on floats using rstrip('0') to get rid of the trailing zeros:     ...         s = '{:g}'.format(dec)     if '.' in s and 'e' not in s:         s = s.rstrip('0')         s = s.rstrip('.')     return s
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Hrvoje Nikšić-3 On 2015-02-12, Ian Kelly wrote: > On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nik?i? wrote: > >> {:.15g} is supposed to give 15 digits of precision, but with trailing >> zeros removed. > > The doc says with "insignificant" trailing zeros removed, not all > trailing zeros. Can somebody explain the difference between "significant" and "insignificant" tailing zeros to somebody who barely passed his single numerical methods class?  [Though I have, on occasion, had to tinker with the innards of SW floating point libraries and could fish a hardcopy of IEEE-754 out of a filing cabinet if needed.] -- Grant Edwards               grant.b.edwards        Yow! My polyvinyl cowboy                                   at               wallet was made in Hong                               gmail.com            Kong by Montgomery Clift!
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Hrvoje Nikšić-3 On Fri, Feb 13, 2015 at 2:26 AM, Hrvoje Nik?i? wrote: > Ian Kelly writes: >> When you specify the a precision of 15 in your format string, you're >> telling it to take the first 15 of those. It doesn't care that the >> last couple of those are zeros, because as far as it's concerned, >> those digits are significant. > > OK, it's a bit surprising, but also consistent with the rest of the > decimal module. Thanks for clearing it up. > > My concrete use case is printing an arbitrary fraction as a > user-readable decimal, rounded to the specified number of digits, and > using the exponential notation where appropriate: > > import decimal > _dec_fmt_context = decimal.Context(prec=15, rounding=decimal.ROUND_HALF_UP) > def _format(frac): >     with decimal.localcontext(_dec_fmt_context): >         dec = decimal.Decimal(frac.numerator) / > decimal.Decimal(frac.denominator) >         return '{:g}'.format(dec) > > The decimal obtained by dividing the numerator with the denominator > includes trailing zeros. Calling normalize() to get rid of them will > have the unfortunate side effect of turning 9806650 into 9.80665e+6, > and the method recommended in the documentation: > > def remove_exponent(d): >     return d.quantize(decimal.Decimal(1)) if d == d.to_integral() else > d.normalize() > > ...will raise "decimal.InvalidOperation: quantize result has too many > digits for current context" when the number is too large. In that case I think you just want to normalize instead. So: >>> def remove_exponent(d): ...   if d == d.to_integral(): ...     try: ...       return d.quantize(1) ...     except decimal.InvalidOperation: ...       pass ...   return d.normalize() ... >>> remove_exponent(D('123000000')) Decimal('123000000') >>> remove_exponent(D('123.4567')) Decimal('123.4567') >>> remove_exponent(D('123.4567890')) Decimal('123.456789') >>> remove_exponent(D('123e6')) Decimal('123000000') >>> remove_exponent(D('1234567890123456789012345678901234567890')) Decimal('1.234567890123456789012345679E+39')
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Grant Edwards-7 On Fri, Feb 13, 2015 at 7:02 AM, Grant Edwards wrote: > On 2015-02-12, Ian Kelly wrote: >> On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nik?i? wrote: >> >>> {:.15g} is supposed to give 15 digits of precision, but with trailing >>> zeros removed. >> >> The doc says with "insignificant" trailing zeros removed, not all >> trailing zeros. > > Can somebody explain the difference between "significant" and > "insignificant" tailing zeros to somebody who barely passed his single > numerical methods class?  [Though I have, on occasion, had to tinker > with the innards of SW floating point libraries and could fish a > hardcopy of IEEE-754 out of a filing cabinet if needed.] Significant digits are within the precision of the calculation. Writing 1.230 indicates that the fourth digit is known to be zero. Writing 1.23 outside a context of exact calculation indicates that the fourth digit is unknown due to insufficient precision.
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Grant Edwards-7 On 2015-02-13, Ian Kelly wrote: > On Fri, Feb 13, 2015 at 7:02 AM, Grant Edwards wrote: >> On 2015-02-12, Ian Kelly wrote: >>> On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nik?i? wrote: >>> >>>> {:.15g} is supposed to give 15 digits of precision, but with trailing >>>> zeros removed. >>> >>> The doc says with "insignificant" trailing zeros removed, not all >>> trailing zeros. >> >> Can somebody explain the difference between "significant" and >> "insignificant" tailing zeros to somebody who barely passed his single >> numerical methods class?  [Though I have, on occasion, had to tinker >> with the innards of SW floating point libraries and could fish a >> hardcopy of IEEE-754 out of a filing cabinet if needed.] > > Significant digits are within the precision of the calculation. > Writing 1.230 indicates that the fourth digit is known to be zero. > Writing 1.23 outside a context of exact calculation indicates that the > fourth digit is unknown due to insufficient precision. I knew that, but I was asking in the context of float/decimal's formatting function.  I didn't realize that float and/or decimal had a "significant digit" property, and therefore possess significant vs. insignificant trailing zeros when represented in base-10. -- Grant Edwards               grant.b.edwards        Yow! Mr and Mrs PED, can I                                   at               borrow 26.7% of the RAYON                               gmail.com            TEXTILE production of the                                                    INDONESIAN archipelago?
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On Fri, Feb 13, 2015 at 1:33 PM, Grant Edwards wrote: > On 2015-02-13, Ian Kelly wrote: >> On Fri, Feb 13, 2015 at 7:02 AM, Grant Edwards wrote: >>> On 2015-02-12, Ian Kelly wrote: >>>> On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nik?i? wrote: >>>> >>>>> {:.15g} is supposed to give 15 digits of precision, but with trailing >>>>> zeros removed. >>>> >>>> The doc says with "insignificant" trailing zeros removed, not all >>>> trailing zeros. >>> >>> Can somebody explain the difference between "significant" and >>> "insignificant" tailing zeros to somebody who barely passed his single >>> numerical methods class?  [Though I have, on occasion, had to tinker >>> with the innards of SW floating point libraries and could fish a >>> hardcopy of IEEE-754 out of a filing cabinet if needed.] >> >> Significant digits are within the precision of the calculation. >> Writing 1.230 indicates that the fourth digit is known to be zero. >> Writing 1.23 outside a context of exact calculation indicates that the >> fourth digit is unknown due to insufficient precision. > > I knew that, but I was asking in the context of float/decimal's > formatting function.  I didn't realize that float and/or decimal had a > "significant digit" property, and therefore possess significant vs. > insignificant trailing zeros when represented in base-10. A Decimal object consists of a sign, a tuple of decimal digits, and an exponent. If the digits are, e.g, (1, 2, 3, 0, 0, 0), then that would be equal to the Decimal with the digits (1, 2, 3) and the same sign and exponent, but the explicit presence of the trailing zeros indicates their significance. If this doesn't answer your question, then I'm not really sure what you're asking.
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Grant Edwards-7 On 02/13/2015 03:33 PM, Grant Edwards wrote: > On 2015-02-13, Ian Kelly wrote: >> Significant digits are within the precision of the calculation. >> Writing 1.230 indicates that the fourth digit is known to be zero. >> Writing 1.23 outside a context of exact calculation indicates that the >> fourth digit is unknown due to insufficient precision. > > I knew that, but I was asking in the context of float/decimal's > formatting function.  I didn't realize that float and/or decimal had a > "significant digit" property, and therefore possess significant vs. > insignificant trailing zeros when represented in base-10. > Just jumping in here, and somebody please correct me if I mess it up. Built-in binary floating point (float) has a fixed number of bits for mantissa, and separate bits for exponent and sign.  Because of those fixed number of bits, no assumption can be made as to how many of them are relevant. On the other hand, the Decimal package has a way that the programmer can tell how many digits to use at each stage of the calculation.  So if the programmer bothered to set it to the correct precision, the print logic (could) use that to decide about trailing zeroes.  I have no idea whether it does, but this thread would seem to say it does. I also have no definite opinion as to whether that's reasonable, or whether most calculations are done by setting digits to about twice what's needed, and rounding at the end.  I know I did exactly that when I wrote a variable length math package to double-check the accuracy of a fixed precision package I was developing, 40 years ago  (long before the IEEE-754 standard began meetings).  The fixed precision package was fast, and used lots of clever(?) shortcuts for speed.  The variable one was written very brute force, ran maybe 100 times slower (on another machine), but the results could be compared with automatic algorithms. For simple arithmetic, not too big a deal, but for transcendentals, the error analysis was very important.  For example, the fast algorithm was a custom chebyshev, while the reference implementation was Taylor series. -- DaveA
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Grant Edwards-7 On 2015-02-13, Dave Angel wrote: > On 02/13/2015 03:33 PM, Grant Edwards wrote: >> On 2015-02-13, Ian Kelly wrote: >> >>> Significant digits are within the precision of the calculation. >>> Writing 1.230 indicates that the fourth digit is known to be zero. >>> Writing 1.23 outside a context of exact calculation indicates that the >>> fourth digit is unknown due to insufficient precision. >> >> I knew that, but I was asking in the context of float/decimal's >> formatting function.  I didn't realize that float and/or decimal had a >> "significant digit" property, and therefore possess significant vs. >> insignificant trailing zeros when represented in base-10. > > Just jumping in here, and somebody please correct me if I mess it up. > > Built-in binary floating point (float) has a fixed number of bits for > mantissa, and separate bits for exponent and sign.  Because of those > fixed number of bits, no assumption can be made as to how many of them > are relevant. Right. > On the other hand, the Decimal package has a way that the programmer > can tell how many digits to use at each stage of the calculation. That's what surpised me.  From TFM: https://docs.python.org/2/library/decimal.html: * The decimal module incorporates a notion of significant places so that    1.30 + 1.20 is 2.50. The trailing zero is kept to indicate    significance. This is the customary presentation for monetary    applications. For multiplication, the ?schoolbook? approach uses    all the figures in the multiplicands. For instance, 1.3 * 1.2 gives    1.56 while 1.30 * 1.20 gives 1.5600. > So if the programmer bothered to set it to the correct precision, the > print logic (could) use that to decide about trailing zeroes.  I have > no idea whether it does, but this thread would seem to say it does. It seems to. Pretty cool. -- Grant Edwards               grant.b.edwards        Yow! LOOK!!  Sullen                                   at               American teens wearing                               gmail.com            MADRAS shorts and "Flock of                                                    Seagulls" HAIRCUTS!
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On Fri, Feb 13, 2015 at 2:22 PM, Grant Edwards wrote: > On 2015-02-13, Dave Angel wrote: >> On the other hand, the Decimal package has a way that the programmer >> can tell how many digits to use at each stage of the calculation. > > That's what surpised me.  From TFM: > > https://docs.python.org/2/library/decimal.html:> >  * The decimal module incorporates a notion of significant places so that >    1.30 + 1.20 is 2.50. The trailing zero is kept to indicate >    significance. This is the customary presentation for monetary >    applications. For multiplication, the ?schoolbook? approach uses >    all the figures in the multiplicands. For instance, 1.3 * 1.2 gives >    1.56 while 1.30 * 1.20 gives 1.5600. Huh. That approach for multiplication is definitely not what I was taught in school. I was taught that the number of significant digits in the product is the lesser of the number of significant digits in either of the measured multiplicands. So 1.30 * 1.20 would be 1.56, while 1.3 * 1.2 would just be 1.6. Wikipedia appears to agree with me: http://en.wikipedia.org/wiki/Significance_arithmetic#Multiplication_and_division_using_significance_arithmeticMoreover: >>> D('1.304') * D('1.204') Decimal('1.570016') >>> D('1.295') * D('1.195') Decimal('1.547525') So 1.30 * 1.20 could be written approximately as 1.56 ? 0.01. Given that, I don't understand how the trailing zeros in 1.5600 could possibly be considered significant.
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On Fri, Feb 13, 2015 at 2:40 PM, Ian Kelly wrote: > On Fri, Feb 13, 2015 at 2:22 PM, Grant Edwards wrote: >> On 2015-02-13, Dave Angel wrote: >>> On the other hand, the Decimal package has a way that the programmer >>> can tell how many digits to use at each stage of the calculation. >> >> That's what surpised me.  From TFM: >> >> https://docs.python.org/2/library/decimal.html:>> >>  * The decimal module incorporates a notion of significant places so that >>    1.30 + 1.20 is 2.50. The trailing zero is kept to indicate >>    significance. This is the customary presentation for monetary >>    applications. For multiplication, the ?schoolbook? approach uses >>    all the figures in the multiplicands. For instance, 1.3 * 1.2 gives >>    1.56 while 1.30 * 1.20 gives 1.5600. > > Huh. That approach for multiplication is definitely not what I was > taught in school. I was taught that the number of significant digits > in the product is the lesser of the number of significant digits in > either of the measured multiplicands. So 1.30 * 1.20 would be 1.56, > while 1.3 * 1.2 would just be 1.6. Wikipedia appears to agree with me: > > http://en.wikipedia.org/wiki/Significance_arithmetic#Multiplication_and_division_using_significance_arithmetic> > Moreover: > >>>> D('1.304') * D('1.204') > Decimal('1.570016') >>>> D('1.295') * D('1.195') > Decimal('1.547525') > > So 1.30 * 1.20 could be written approximately as 1.56 ? 0.01. Given > that, I don't understand how the trailing zeros in 1.5600 could > possibly be considered significant. I guess the point here is that the paragraph isn't really talking about significance arithmetic; it's explaining how it decides how many digits to keep in the result. It may be fine for 1.30 * 1.20 to return 1.56, but it would be very confusing if 1.35 * 1.25 returned 1.69 instead of 1.6875. The wording of the paragraph seems misleading, though.
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 In reply to this post by Ian Kelly-2 On 12/02/2015 23:46, Ian Kelly wrote: > On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nik?i? wrote: >>>>>>>> from decimal import Decimal as D >>>>>>>> x = D(1)/D(999) >>>>>>>> '{:.15g}'.format(x) >>>>> >>>>> '0.00100100100100100' >> [...] >>>> I'd say it's a bug.  P is 15, you've got 17 digits after the decimal place >>>> and two of those are insignificant trailing zeros. >>> >>> Actually it's the float version that doesn't match the documentation. >>> In the decimal version, sure there are 17 digits after the decimal >>> place there, but the first two -- which are leading zeroes -- would >>> not normally be considered significant. >> >> {:.15g} is supposed to give 15 digits of precision, but with trailing >> zeros removed. > > The doc says with "insignificant" trailing zeros removed, not all > trailing zeros. > >> For example, '{:.15g}'.format(Decimal('0.5')) should >> yield '0.5', not '0.500000000000000' -- and, it indeed does.  It is >> only for some numbers that trailing zeros are not removed, which looks >> like a bug.  The behavior of floats matches both the documentation and >> other languages using the 'g' decimal format, such as C. > > Ah, I see now what's going on here. With floats, there is really no > notion of significant digits. The values 0.5 and 0.50000 are > completely equivalent. With decimals, that's not exactly true; if you > give the decimal a trailing zero then you are telling it that the zero > is significant. > >>>> Decimal('0.5') > Decimal('0.5') >>>> Decimal('0.50000') > Decimal('0.50000') >>>> Decimal('0.5').as_tuple() > DecimalTuple(sign=0, digits=(5,), exponent=-1) >>>> Decimal('0.50000').as_tuple() > DecimalTuple(sign=0, digits=(5, 0, 0, 0, 0), exponent=-5) > > These are distinct; the decimal knows how many significant digits you > passed it. As a result, these are also distinct: > >>>> '{:.4g}'.format(Decimal('0.5')) > '0.5' >>>> '{:.4g}'.format(Decimal('0.50000')) > '0.5000' > > Now what happens in your original example of 1/999? The default > decimal context uses 28 digits of precision, so the result of that > calculation will have 28 significant digits in it. > >>>> decimal.getcontext().prec > 28 >>>> Decimal(1) / Decimal(999) > Decimal('0.001001001001001001001001001001') > > When you specify the a precision of 15 in your format string, you're > telling it to take the first 15 of those. It doesn't care that the > last couple of those are zeros, because as far as it's concerned, > those digits are significant. > I still think it's a bug as the 'p' being referred to in the OP's original message is "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'".  In other words is has nothing to do with the precision of the underlying number. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On Fri, Feb 13, 2015 at 4:05 PM, Mark Lawrence wrote: > I still think it's a bug as the 'p' being referred to in the OP's original > message is "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'".  In other words is has > nothing to do with the precision of the underlying number. I read that paragraph as describing generally what the precision means, with the table below detailing more specifically how it is used. I think for 'g' this is just trying to contrast it with 'f' where it really is just the number of digits displayed after the decimal point. The table entry for 'g' on the other hand quite clearly says, "for a given precision p >= 1, this rounds the number to p significant digits".
Open this post in threaded view
|

## Floating point "g" format not stripping trailing zeros

 On 14/02/2015 00:11, Ian Kelly wrote: > On Fri, Feb 13, 2015 at 4:05 PM, Mark Lawrence wrote: >> I still think it's a bug as the 'p' being referred to in the OP's original >> message is "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'".  In other words is has >> nothing to do with the precision of the underlying number. > > I read that paragraph as describing generally what the precision > means, with the table below detailing more specifically how it is > used. I think for 'g' this is just trying to contrast it with 'f' > where it really is just the number of digits displayed after the > decimal point. The table entry for 'g' on the other hand quite clearly > says, "for a given precision p >= 1, this rounds the number to p > significant digits". > With insignificant trailing zeros removed.  So if I'm asking for 15 significant digits *in the output* I don't expect to see those zeros as I don't see them as significant.  If I did I'd have p set higher. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence