Re: Floating point g format not stripping trailing zeros

2015-02-14 Thread Ian Kelly
On Fri, Feb 13, 2015 at 6:22 PM, Mark Lawrence breamore...@yahoo.co.uk wrote:
 On 14/02/2015 00:11, Ian Kelly wrote:

 On Fri, Feb 13, 2015 at 4:05 PM, Mark Lawrence breamore...@yahoo.co.uk
 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.

So you think you should have to request 17 significant digits in order
to have 15 of them included?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Hrvoje Nikšić
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
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Grant Edwards
On 2015-02-12, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nikšić hnik...@gmail.com 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.edwardsYow! My polyvinyl cowboy
  at   wallet was made in Hong
  gmail.comKong by Montgomery Clift!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Ian Kelly
On Fri, Feb 13, 2015 at 2:26 AM, Hrvoje Nikšić hnik...@gmail.com 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('12300'))
Decimal('12300')
 remove_exponent(D('123.4567'))
Decimal('123.4567')
 remove_exponent(D('123.4567890'))
Decimal('123.456789')
 remove_exponent(D('123e6'))
Decimal('12300')
 remove_exponent(D('1234567890123456789012345678901234567890'))
Decimal('1.234567890123456789012345679E+39')
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Ian Kelly
On Fri, Feb 13, 2015 at 7:02 AM, Grant Edwards invalid@invalid.invalid wrote:
 On 2015-02-12, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nikšić hnik...@gmail.com 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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Grant Edwards
On 2015-02-13, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Fri, Feb 13, 2015 at 7:02 AM, Grant Edwards invalid@invalid.invalid 
 wrote:
 On 2015-02-12, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nikšić hnik...@gmail.com 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.edwardsYow! Mr and Mrs PED, can I
  at   borrow 26.7% of the RAYON
  gmail.comTEXTILE production of the
   INDONESIAN archipelago?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Mark Lawrence

On 12/02/2015 23:46, Ian Kelly wrote:

On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nikšić hnik...@gmail.com 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.500' -- 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.5 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.5')

Decimal('0.5')

Decimal('0.5').as_tuple()

DecimalTuple(sign=0, digits=(5,), exponent=-1)

Decimal('0.5').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.5'))

'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

--
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Ian Kelly
On Fri, Feb 13, 2015 at 1:33 PM, Grant Edwards invalid@invalid.invalid wrote:
 On 2015-02-13, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Fri, Feb 13, 2015 at 7:02 AM, Grant Edwards invalid@invalid.invalid 
 wrote:
 On 2015-02-12, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nikšić hnik...@gmail.com 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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Dave Angel

On 02/13/2015 03:33 PM, Grant Edwards wrote:

On 2015-02-13, Ian Kelly ian.g.ke...@gmail.com 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
--
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Ian Kelly
On Fri, Feb 13, 2015 at 2:22 PM, Grant Edwards invalid@invalid.invalid wrote:
 On 2015-02-13, Dave Angel da...@davea.name 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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Grant Edwards
On 2015-02-13, Dave Angel da...@davea.name wrote:
 On 02/13/2015 03:33 PM, Grant Edwards wrote:
 On 2015-02-13, Ian Kelly ian.g.ke...@gmail.com 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.edwardsYow! LOOK!!  Sullen
  at   American teens wearing
  gmail.comMADRAS shorts and Flock of
   Seagulls HAIRCUTS!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Ian Kelly
On Fri, Feb 13, 2015 at 2:40 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Fri, Feb 13, 2015 at 2:22 PM, Grant Edwards invalid@invalid.invalid 
 wrote:
 On 2015-02-13, Dave Angel da...@davea.name 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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Ian Kelly
On Fri, Feb 13, 2015 at 4:05 PM, Mark Lawrence breamore...@yahoo.co.uk 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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Mark Lawrence

On 14/02/2015 00:11, Ian Kelly wrote:

On Fri, Feb 13, 2015 at 4:05 PM, Mark Lawrence breamore...@yahoo.co.uk 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

--
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-13 Thread Gregory Ewing

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.


But it does say that insignificant trailing
zeros are removed, not just trailing zeros
are removed.

However, it's possible that insignificant
was just intended to mean after the decimal
point. The specification is a bit vague.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-12 Thread Hrvoje Nikšić
  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.500' -- 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'.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-12 Thread Ian Kelly
On Thu, Feb 12, 2015 at 1:23 PM, Hrvoje Nikšić hnik...@gmail.com 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.500' -- 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.5 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.5')
Decimal('0.5')
 Decimal('0.5').as_tuple()
DecimalTuple(sign=0, digits=(5,), exponent=-1)
 Decimal('0.5').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.5'))
'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.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-11 Thread Mark Lawrence

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

--
https://mail.python.org/mailman/listinfo/python-list


Floating point g format not stripping trailing zeros

2015-02-11 Thread Hrvoje Nikšić
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?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-11 Thread Ian Kelly
On Wed, Feb 11, 2015 at 3:19 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Wed, Feb 11, 2015 at 2:48 PM, Mark Lawrence breamore...@yahoo.co.uk 
 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(99900))
 '1.00100100100100e-9'
 '{:.15g}'.format(1./99900)
 '1.001001001001e-09'

Although here's something else that is definitely an issue with the
decimal formatting:

 '{:.15g}'.format(D(1)/D(999000))
'0.0100100100100100'

This has an exponent of -6, so according to the docs it should be
formatted in exponential notation.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point g format not stripping trailing zeros

2015-02-11 Thread Ian Kelly
On Wed, Feb 11, 2015 at 2:48 PM, Mark Lawrence breamore...@yahoo.co.uk 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(99900))
'1.00100100100100e-9'
 '{:.15g}'.format(1./99900)
'1.001001001001e-09'
-- 
https://mail.python.org/mailman/listinfo/python-list