Comparisons and sorting of a numeric class....
davea at davea.name
Tue Jan 6 12:21:14 CET 2015
On 01/06/2015 05:27 AM, Andrew Robinson wrote:
> I'm building a custom numeric class that works with values that have
> uncertainty and am wanting to make it as compatible with floating point
> objects as possible -- so as to be usable in legacy code with minimal
> rewites; but but I am having trouble understanding how to handle
> magnitude comparison return values for __lt__ __gt__ etc.
> The problem with magnitude comparisons in my class is that the
> comparison may fail to be True for various reasons, and in various ways,
> but it's important for programming to retain the general reason a
> comparison wasn't strictly 'True'.
> For example, to 1 significant figure, I can write two values
> a=mynum(0.1) and b=mynum(0.01) ; as written both of them have an
> uncertainty of 1 least significant figure, so it is possible both values
> are really a 0. But, there is a bias/mean/average which suggests that
> more often than not -- 0.1 will be bigger than 0.01. So, what is the
> proper response of a>b ?, the answer is that a>b depends on the context
> of how the values were obtained and what is being done with them,
> although strictly speaking 'a' is not greater than 'b' in this case,
> although 'a' has a much better chance of being greater than 'b' on
> average which may be important for the user to know.
> Where I'm getting stuck is how to encode the return values of the
> comparison operators to be compatible with python floating point object
> return values (and python's sort algorithms for lists of floats) but
> still give extra functionality that is needed for uncertainty ... and as
> I'm writing in python 2.xx but with an eye toward python 3 in the
> future, I've become concerned that __cmp__ has been discontinued so that
> I need to write this using only __gt__() and friends. I don't know how
> to do it.
> What I would like is for operators like '>' to return a boolean True or
> False equivalent, which also encodes the reason for failure in one of
> five ways:
> True: Sufficient information and confidence exists that the
> comparison is thoroughly True.
> PartTrue: The comparison is uncertain for any single sample, but True
> is at least minimally more probable.
> Unbiased: The comparison is uncertain for any single sample.
> PartFalse: The comparison is uncertain for any single sample, but
> False is at least minimally more probable.
> False: Sufficient information and confidence exists that the
> comparison is thoroughly False.
Just a few comments, not a thorough examination. And I don't have time
to actually try it today.
1) to subclass built-in types, you frequently have to implement your own
constructor. You probably tried it by only implementing the
initializer. The constructor has the name __new__
and you probably should read:
2) to be sortable, your comparison mechanism needs to be stable. (I
think that's the word). Anyway, if a < b and b < c, then a must be <
c. It's not clear that you can accomplish that with the approach you're
describing. But if you modify your definition for values near zero, it
may be possible.
3) Your user will have to be aware that she's not using regular float
values. Sooner or later some functions will have to be used
differently. But you should still be able to mostly preserve the illusion.
4) When you convert to Python version 3.x, you'll have to re-study all
these issues. It may be to your advantage to do both versions at once,
or to just support version 3.x
> By default, only True would evaluate in conditional statement as a
> logical True. All other values would be equivalent to False, but
> hopefully, a programmer could find out which 'False' was returned by
> some kind of object inspection or operator, like:
> if (a>b) is PartTrue: print "I don't really know if 'a' really is
> greater than 'b'. but it might be"
> if (a>b) > Unbiased: print "a sorts after b because it's at least more
> probable that a>b than not."
> if (a>b): print "this message will not print if the value 'b' might
> occasionally be less than or equal to 'a'."
Those should all be possible.
> For sorting, it would be ideal if the sorting algorithms min(), max(),
> etc. could automatically recognize that:
> False < PartFalse < Unknown < PartTrue < True.
> But, even if that can't be done -- if there were a way, or method I
> could add to my classes, which would intercept sort functions and
> replace an absolute certain compare function with a merely Unbiased
> detecting one; sort functions would all operate properly.
> However, I'm not sure how to create these return values nor do I know
> how to get the sort() functions to use them.
> I've tried subclassing float() to see if I could actually make a
> subclass that inherited all that float has, and be able to add extra
> methods for my own use -- but Python doesn't seem to allow subclassing
> float. I either am not doing it right, or it can't be done.
> So, I'm not sure I can subclass boolean either because that too is a
> built in class ... but I'm not sure how else to make an object that
> acts as boolean False, but can be differentiated from false by the 'is'
> operator. It's frustrating -- what good is subclassing, if one cant
> subclass all the base classes the language has?
As I said above, make sure you have a constructor. If you still get an
error, post a message that shows exactly what you did, and what
exception you saw.
> What other approaches can I take?
> 'False' is a singleton, so I was pretty sure this wouldn't work -- but I
> tried it...
> PartTrue = False
> if (1>2) is PartTrue: print "This is an obvious failure... False is not
> the object PartTrue."
You misunderstand the term singleton in this context. When you execute
PartTrue = False
you are just rebinding PartTrue to the object called False. There's
still only one object.
More information about the Python-list