Title: Scientific formatting of decimal 0 different from float 0
Type: Stage:
Components: Versions:
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Aaron.Meurer, eric.smith, facundobatista, mark.dickinson, rhettinger, skrah
Priority: normal Keywords:

Created on 2017-10-03 21:46 by Aaron.Meurer, last changed 2017-10-04 19:02 by skrah.

Messages (7)
msg303653 - (view) Author: Aaron Meurer (Aaron.Meurer) Date: 2017-10-03 21:46
>>> '{:+.19e}'.format(0.)
>>> import decimal
>>> '{:+.19e}'.format(decimal.Decimal(0))

Note the decimal uses e+19 instead of e+00. Obviously it's still mathematically correct, but it's annoying to have anything other than e+00 for a 0 value.
msg303672 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2017-10-04 06:23
The aim here is to capture the original Decimal value where possible, including the exponent information. (Unlike floats, trailing zeros in a `Decimal` instance are significant.)

>>> from decimal import Decimal
>>> Decimal('+0.0000000000000000000e+19')
>>> Decimal('+0.0000000000000000000e+00')
msg303719 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2017-10-04 17:40
Yes, from the point of view of decimal it's the right thing:

>>> x = Decimal("1e25").quantize(Decimal("1e30"))
>>> x
>>> '{:+.19e}'.format(x)

The original magnitude should be traceable (the example is not
perfect but the first thing that quickly came to mind).
msg303720 - (view) Author: Aaron Meurer (Aaron.Meurer) Date: 2017-10-04 17:44
I guess I would expect that to be captured by the number of zeros printed (and obviously doing a string format operation with a set number of digits destroys that information).
msg303723 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2017-10-04 18:11
I don't think format() destroys the information:

>>> '{:+.19e}'.format(Decimal("0.00000e20"))

The original magnitude was e+15, after formatting it's still e+15.
msg303725 - (view) Author: Aaron Meurer (Aaron.Meurer) Date: 2017-10-04 18:36
I meant that format() destroys information in a decimal in general. Obviously if you have n digits of precision and format with m < n, then you lose information. 

I also can't help but feel that we're mixing up "trailing zeros" (i.e., precision), and "exponent" (magnitude), which should be orthogonal. I'm assuming that a decimal is represented internally as base*10**exponent. I'm also assuming that Decimal(0) sets both base and exponent to 0. It doesn't make sense to me that a string formatting operation that requests a certain number of digits of precision should change the exponent. 

I get that 0.0 is different from 0.00000, but in that case, they should print differently: as '0.0' and '0.00000'. It seems sly to try to maintain that through a format operation via the exponent, especially when format *in general* loses precision information for a decimal anyway (by "format" I mean format with a set number of digits requested). Especially since that "trick" only works for exactly one number, zero. If you do '{:+.30e}'.format(Decimal('1.0000000000000000000')) or '{:+.10e}'.format(Decimal('1.0000000000000000000')), no such trick is used, because no such trick can be used. You just lose information. 

I'm sure my mental model is off here. I'm used to sympy.Float/mpmath.mpf where values like 0*2**i are normalized to i = 0 (e.g. mpmath.mpf((0, 0, 20, 0))._mpf_ gives (0, 0, 0, 0)), so this problem never comes up in the code that I'm used to.
msg303728 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2017-10-04 19:02
> I'm also assuming that Decimal(0) sets both base and exponent to 0.

No, 0 is really special in the IBM specification. The magnitude is
kept, the precision is not.

>>> Decimal("0e10") * Decimal("0e20") 

>>> Decimal("0.000e10")

So we're basically doing the reverse of the above in formatting when a
precision is given.
Date User Action Args
2017-10-04 19:02:15skrahsetmessages: + msg303728
2017-10-04 18:36:14Aaron.Meurersetmessages: + msg303725
2017-10-04 18:11:11skrahsetmessages: + msg303723
2017-10-04 17:44:30Aaron.Meurersetmessages: + msg303720
2017-10-04 17:40:01skrahsetmessages: + msg303719
2017-10-04 14:27:35eric.smithsetnosy: + eric.smith
2017-10-04 06:23:48mark.dickinsonsetmessages: + msg303672
2017-10-04 05:39:16rhettingersetnosy: + rhettinger, facundobatista, mark.dickinson, skrah
2017-10-03 21:46:21Aaron.Meurercreate