Issue5448
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2009-03-08 20:23 by dlesco, last changed 2022-04-11 14:56 by admin. This issue is now closed.
Messages (3) | |||
---|---|---|---|
msg83328 - (view) | Author: Daniel Lescohier (dlesco) | Date: 2009-03-08 20:23 | |
I would like to get the decimal precision of decimal.Decimal objects (for my application, in order to validate whether a Decimal value will fit in the defined decimal precision of a database field). The way I found to get it was with: precision = len(value._int) where value is a decimal.Decimal object. However, this uses a private API (_int). I would like to have a public API to get the decimal precision of a Decimal. I propose we add the following to the decimal.Decimal class: @property def precision(self): """The precision of this Decimal value.""" return len(self._int) decimal.Context has a precision for calculations. decimal.Decimal.precision is the minimum precision needed to represent that value, not the precision that was used in calculating it. If one wants to, one can actually use Decimal.precision to set your Context's precision: d1 = decimal.Decimal('999') d2 = d1 context.prec = d1.precision + d2.precision d3 = d1 * d2 Open for debate is whether to name it Decimal.prec to mirror Context.prec. We'd have to choose one or the other or both: @property def precision(self): """The precision of this Decimal value.""" return len(self._int) prec = precision |
|||
msg83369 - (view) | Author: Raymond Hettinger (rhettinger) * | Date: 2009-03-09 11:30 | |
FWIW, there is a public API to get at the same information: Decimal.as_tuple(). That being said, I don't see how your len(value._int) test could be correct. The exponent will potentially shift the value way out-of-bounds for a database. Consider Decimal('999E+10') or Decimal('999E-10') whose database storage sizes do not fit in a DECIMAL(7,4) field eventhough their len(value._int) is three. To see if the fractional part of a decimal number fits in a database, set the context precision to the database precision and quantize the decimal to the allowed number of decimal places. If the Inexact flag gets set, then it didn't fit. -1 on extending the API any further from the underlying IBM specification. |
|||
msg83393 - (view) | Author: Daniel Lescohier (dlesco) | Date: 2009-03-09 16:13 | |
I had other code to check scale, but you are right, I should use quantize. There is certainly a lot to absorb in the IBM decimal specification. I really appreciate you pointing me to quantize and Inexact. I guess I inadvertently used the issue tracker for help on the decimal module, I didn't really mean to do that, I really thought there was a need for Decimal.precision. The other unrelated issue I entered (#5445) should be more of a real issue. My code constructs a conversion/validation closure for every field in the Schema, based on a SchemaField definition for each field. My SchemaFieldDecimal class includes precision and scale parameters, and now I'm going to add a rounding parameter, with None meaning raise an error on Inexact. So pseudo-code for the fix: scale = None if scale is None else Decimal((0,(1,),-scale)) traps = (InvalidOperation, Inexact) if rounding is None else (InvalidOperation,) context = Context(prec=precision, rounding=rounding, traps=traps) doing the conversion/validation: For case if scale is not None: try: with context: value = Decimal(value).quantize(scale) except handlers... For case if scale is None: try: with context: value = Decimal(value)+Decimal(0) # will round or raise Inexact except handlers... |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:56:46 | admin | set | github: 49698 |
2009-03-09 16:13:41 | dlesco | set | messages: + msg83393 |
2009-03-09 11:30:08 | rhettinger | set | status: open -> closed nosy: + rhettinger messages: + msg83369 resolution: rejected |
2009-03-08 20:23:44 | dlesco | create |