[Python-ideas] numerical type combining integer and float/decimal properties [Was: Re: Python Numbers as Human Concept Decimal System]

Ron Adam ron3200 at gmail.com
Tue Mar 11 07:36:38 CET 2014


On 03/10/2014 12:48 PM, Wolfgang Maier wrote:
> Going back to Mark Harris' initial proposal of unifying numeric types (which
> I am not trying to support in any way here), such a type would even allow to
> unify int and float since an ints could be considered a subset of the new
> type with a fractional part of zero.


This turned out a bit longer than I intended.  I think it is the correct 
approach to what I think is the intent of the number unifications 
suggestions.  Trim it down a bit, and add some examples and it's a good 
start to a PEP.   ;-)


I think adding a new number type isn't going to help that much, although it 
won't hurt either.

(Hoping this is a more practical direction for these discussions.)



General Proposal:
=================

Add a BaseValue class for creating context dependent values like a 
CurrencyValue class, or StatisticValue class.

The Value class should not specify any particular number type.  That is an 
implementation detail of a subclass.

The Value class will define how to round, compare, and track error ranges 
when used in calculations.  And will use ValueContext objects to adjust 
that as needed.

Add a ValueContext class to create context parameter objects.  These 
objects will be used to set a Value class's context for rounding, number of 
significant digits, and tracking error ranges.

The ValueContext objects should be very simple, and loosely defined in the 
same way slice objects are.  They are only used for passing the context 
parameters.  (Like slice objects pass index's, but probably by called 
methods rather than by syntax.)



Introduction:
=============

There have been a number of suggestions to unify numbers in order to make 
them easier to use for less mathematically inclined users to do more 
complex calculations without having to know quite as much about the 
underlying type of number.  There is no magic wand that will make it 
completely painless, but we can make things easier to get right to an 
average programmer with average to good math skills.  (Probably the normal 
group for most beginner programmer students.)

The basic issue I see isn't with the number types, but with how we use 
them.  (And how we can us them better)  There are a lot of parts that need 
to work both independently and together at the same time.

Currently It's up to the programmer to keep track of significant digits 
(and significant error), any rounding that may need to be done, and to do 
it all correctly.  There are many places where it can go wrong, and where 
getting it right requires a good understanding of these concepts within the 
speciality they are being used in.

The Decimal module tries to reduce that work, and also reduce errors, and 
increase overall accuracy, all at the same time.   But that doesn't help 
the existing number types.  Also while just using the decimal type isn't 
that difficult, using the other features it has correctly isn't as easy.

It's not easy to mix and match these ideas and come up with a usable, and 
reusable, interface for doing many similar types of calculations correctly 
as each value in a calculation (or function call), may not need the same 
exact requirements.

Possibly the broadest, but still practical viewpoint, gives three kinds of 
numbers.  A number kind as described here, refers to how they are used, and 
is independent of the way it's stored in the computer.  The number kind is 
what determines some of the requirements of a calculation or comparison.

If we consider that how a number is used as independent (as much as is 
reasonable) from how the number is stored in memory, then maybe the type is 
less important than the context.



Kinds of Values:
================

1. Measurements: Values which have limited accuracy and need both proper 
rounding and tracking of error ranges.

2. Exact numbers:  Values that really do represent exactly what they are. 
Usually smaller sized numbers, and usually not fractional amounts. 
(includes counters and index's for example)

3. Ideal numbers: Values that are not measurements but can be calculated as 
accurately as needed and generally don't require keeping track of error 
because the significant digits can far exceed any measurements.
    - (Unless you are a theoretical physicist.)
    - (Low quality approximations should be considered a measurement,
       even if it could be calculated accurately to any nth digit.)

Ints, and floating point actually do a very nice job of representing 2. and 
3 in most cases.  And they generally don't need to have a contexts 
associated to them, and usually don't need rounding.  For example, we don't 
want to round index's and counters, they are in the exact group.  And we 
can calculate Pi to what ever we need so that any error range in the value 
is less than significant.


Equality Tests:
===============

Another issue is with equality and how a value's exactness effects that. 
For example if we have two values with an error of +- 1.  We can say it has 
a width of 3.  (Or inexactness of 3)

So we might have this case where two values overlap when you consider the 
width of the value.  (it's +- amount)

      (23 +- 1) < (24 +- 1)  -->  False

Of course those would be objects instead of literals.  (weather or not they 
are decimal, int, or float, isn't important.)

This can be extended to all the other comparison operators.  The usual way 
of dealing with it is to do an error range test, which adds a lot of noise 
to an otherwise simple operation.  Especially if you need to put those in 
many different places.  They aren't quite complex enough to justify 
functions, but complex enough to be bothersome and can be a common source 
of errors.

Exactness, (and rounding, as it's directly related to exactness), are 
independent concepts from how the number is stored in a computer.  (Unless 
you use the wrong type of course, but then I would consider it a bug.)



Values vs Numbers:
=================

One approach is to have a Value class, and a ValueContext object.  The 
ValueContext object may be more like a slice object. It would be up to the 
Value class to interpret it so that it can know how to do the operator 
methods correctly...  __round__, __add__, __eq__, etc...

A base Value class could be used to define types such as a Measurement 
class, Or a Currency class, (and others).

The context API needs to be on a separate Value class/type rather than on 
the number in my opinion.  I think trying to make numbers type also be a 
value is what gets us mixed up. The number is just a scaler for the value. 
  It might also be called vector, but that is a technical term that can be 
confused with other concepts.



Benefits of a Value class:
==========================

* Doesn't change any existing number type.

* Value objects work with any number types.

* Value objects can have a repr that is much nicer, and more meaningful 
than the underlying number type.

* Context sub-class's define how they are used (or act) rather than by what 
kind of computer number they may contain.

* Context (slice like objects) that can be shared, and/or passed between 
Value objects as needed to keep track of rounding, significant digits, and 
error range.

* Can be a library module.


If Value objects is something that can be included into python, then a 
simpler decimal64 type without all the context settings could be used as 
it's just another computer number type with a bit more accuracy if you need it.

A Currency Value type could use Decimal, and the type can be swapped out 
later for the decimal64, as that becomes just an implementation detail for 
he Currency Value class.

Users could do something like that now by defining classes, and probably 
have done it within their applications.  I consider that is a supporting 
argument for this approach, rather than an argument against it.  It still 
takes a fair amount of math knowledge how to get it right.

Making context dependent calculations easier to do, and use, would be very 
nice, and modules using these Value objects could possibly work together 
better.



A good test might be how "Value" objects could be used in the statistics 
module.  Or maybe Mark Harris could try out this idea in his new module.

I think this is the sort of thing Mark was initially looking for.  It's 
really not that complicated if the order of dependencies is correctly 
ordered.  (probably he's got something close to this in it already, just 
with a different name.  (Just a guess, but any solution that solves some of 
this may not be that far off.)



BTW, The new literals would be helpful with this too. +1

Cheers,
    Ron













More information about the Python-ideas mailing list