Open matterhorn103 opened 2 months ago
Sometimes it is not just a question of support but also of making an opinionated decision as to what the result of an operation/function should be.
For example, Quantity
currently supports int(Q)
, but throws an error if the quantity is not dimensionless. Moreover, the decision was already made to just use the underlying Decimal.__int__()
, such that a non-integer number gets rounded. This might be sensible, as the user expects this behaviour by analogy to float
, Decimal
, etc.. However, the rounding is then different to the usual rounding behaviour of Quantity
.
Rounding is another good example. IEEE 754 requires "ties to even" as the default for binary and the recommended default for decimal, on the basis that it results in no bias. Implementation of "ties to away" is also required for decimal implementations. This is what quanstants
uses by default, though, to align with non-technical users' expectations. Again, this opinionated decision should be reviewed.
quanstants
deliberately makes key decisions to break from how Python normally does things (rounding, use of decimal, decimalization of floats as strings). So the question is often whether it should match behaviour of built-in types or to go its own way.
It is important that quantities support standard operations and functions for manipulation as far as possible.
Whether the behaviour should conform to standards/precedent in Python is another question.
The Python docs for numeric types list various operations that are supported by all numeric types (except complex, crucially), but not yet by
Quantity
://
operator (__floordiv__()
)%
operator (__mod__()
, remainder ofQ1 / Q2
)-x
, i.e.__neg__()
, is supported byQuantity
but review for subclasses:Temperature
gives e.g. -50 °C forTemperature(50, °C).__neg__()
,LogarithmicQuantity
doesn't support itabs(Q)
(__abs__()
) – note thatabs(complex("3+4j"))
returns5.0
i.e. the magnitudeint(Q)
is supported but needs review: it defers toDecimal.__int__()
, meaning the rounding is done with a different rounding mode to our defaultfloat(Q)
andint(Q)
need review: they only work on dimensionless quantities. Users may be surprised to not be able to just getQ.number
viafloat()
. In contrast,complex
doesn't support them even if the imaginary part is 0, despite the fact thatcomplex(1+0j) == 1
Q.__complex__()
probably doesn't make sense to implement, unless it just doescomplex(float(Q))
.Q.conjugate()
is necessary if complex numbers are implementedQ.__divmod__()
to give(Q1 // Q2, Q1 % Q2)
Real types (
int
andfloat
) support a few more:This page in the docs says the following methods "can be" defined (but don't have to be) in order to emulate numeric objects (already implemented or reviewed ones are left out):
The
math
module also has various functions that might be sensible to support. We should check though, and ifDecimal
doesn't, maybeQuantity
shouldn't. I also don't know how one goes about supporting them since they act on a quantity and are not methods ofQuantity
itself:Consider implementing the following for special values:
The methods of
Decimal
are naturally all candidates. Many are not meaningful for a quantity, but should be assessed for inclusion:self.number.normalize()
andself.uncertainty.normalize()
self.number.quantize(other.number)
or to essentially do whatQ.round_to_resolution_of()
doesfloat
also has these additional methods:Q.is_integer()
IEEE 754 (floating point standard, also for decimal floating point) has both required operations:
and recommended operations, which often are just compound methods?: