473,325 Members | 2,828 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,325 software developers and data experts.

unittest: Proposal to add failUnlessNear

I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.

My main problem is, that it is only usefull with objects
that can be converted to floats, while there are a whole
bunch of objects that can be almost equal but not so
convertable. The first example coming to mind being
complex numbers.

A secondary objection is that you are limited to
a very specific set of tolerances. If for instance
you want to verify that two numbers differ at most
by 0.0003 you can't specify that.

So I propose to add the following
def failUnlessNear(self, first, second, tolerance=1e-7, msg=None, norm=abs):
"""Fail if the two objects are too far appart as determined
by the distance between them and the tolerance allowed.
"""
if norm(second-first) > tolerance:
raise self.failureException, \
(msg or '%s != %s within %s tolerance' % (`first`, `second`, `tolerance`))
--
Antoon Pardon
Jul 18 '05 #1
31 1632
On Mon, Jul 19, 2004 at 11:06:47AM +0000, Antoon Pardon wrote:
I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.


I'd like to hear more about the uses you envision about this, and
especially about how to choose "tolerance" properly.

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQFA++LfJd01MZaTXX0RAmGkAJ48vek3HG/xN38Qrhc9dTNAOXlhiwCgqACB
6wvCcYIp0ko8m8dJWDgp9E8=
=qbcT
-----END PGP SIGNATURE-----

Jul 18 '05 #2
On 19 Jul 2004 11:06:47 GMT, Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.

My main problem is, that it is only usefull with objects
that can be converted to floats, while there are a whole
bunch of objects that can be almost equal but not so
convertable. The first example coming to mind being
complex numbers.

A secondary objection is that you are limited to
a very specific set of tolerances. If for instance
you want to verify that two numbers differ at most
by 0.0003 you can't specify that.

So I propose to add the following
def failUnlessNear(self, first, second, tolerance=1e-7, msg=None, norm=abs):
"""Fail if the two objects are too far appart as determined
by the distance between them and the tolerance allowed.
"""
if norm(second-first) > tolerance:
raise self.failureException, \
(msg or '%s != %s within %s tolerance' % (`first`, `second`, `tolerance`))
--
Antoon Pardon


How about a more general solution? E.g., how about an optional keyword arg
cmp=comparison_function
passed to failUnlessAlmostEqual? (I'm guessing here, no time to look at it)
E.g., that way for mixed numbers including complex you could (if you thought
it made sense, which I am not necessarily arguing ;-) use e.g.

def special_cmp(x,y): # untested!
diff = complex(x)-complex(y)
return max(cmp(abs(diff.real), tolerance), cmp(abs(diff.imag), tolerance))

and pass cmp=special_cmp as the kwarg.

For special objects, you could define other kinds of nearness, and raise
appropriate informative exceptions if you get non-comparable arguments.

(obviously tolerance has to be defined, so if you want to vary it conveniently,
you could pass it to a factory function that does the above def and returns
it with tolerance captured in a closure referred to by special_cmp).

Or some other way. The point is you get to define the cmp= function as you please
without modifying the framework (once the optional kwarg is implemented).)

gotta go...

Regards,
Bengt Richter
Jul 18 '05 #3
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.

My main problem is, that it is only usefull with objects
that can be converted to floats, while there are a whole
bunch of objects that can be almost equal but not so
convertable. The first example coming to mind being
complex numbers.

A secondary objection is that you are limited to
a very specific set of tolerances. If for instance
you want to verify that two numbers differ at most
by 0.0003 you can't specify that.
Float and complex have two very different issues.
Since I'm maintaining the Python port of FIT, I
had to deal with them. What I did for float was
use the character form of the float to determine
the precision. The default routine appends a
character 5 and then uses this to calculate the
bounds within which the other value must be found.

An example may help. Let's say I want to
test against '6.23e14'. This method would
establish bounds of 6.235e14 and 6.225e14
and then test whether the other number was
within those bounds. (Note that the '5' is
appended before the numbers are converted
to float, however the second bound is calculated
after the conversion.)

There's also a way of prescribing something other
than '5' to append. This approach is due to
Ward Cunningham; what I did was move it
from the ScientificDouble class to the base
float type adapter. (The Java source can be
located in a number of places, including
fit.c2.com and www.fitnesse.org. The Python
source is in the files section of the Extremeprogramming
and fitnesse Yahoo groups. You're welcome
to copy the approach, but since Ward put it
under the GPL, I don't think it can be directly
dropped into unittest.)

Complex, on the other hand, should be dealt
with by calculating the distance between the
two values in the i,j plane
and then seeing if this distance is within a given
bound. The bound should, of course, be a
separately specifiable parameter.

One major issue is that these are very type specific;
the methods should be called something like
"failUnlessFloatWithinTolerance" and
"failUnlessComplexWithinTolerance".

John Roth


So I propose to add the following
def failUnlessNear(self, first, second, tolerance=1e-7, msg=None, norm=abs): """Fail if the two objects are too far appart as determined
by the distance between them and the tolerance allowed.
"""
if norm(second-first) > tolerance:
raise self.failureException, \
(msg or '%s != %s within %s tolerance' % (`first`, `second`, `tolerance`))

--
Antoon Pardon

Jul 18 '05 #4

"Bengt Richter" <bo**@oz.net> wrote in message
news:cd**********@216.39.172.122@theriver.com...
On 19 Jul 2004 11:06:47 GMT, Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.

My main problem is, that it is only usefull with objects
that can be converted to floats, while there are a whole
bunch of objects that can be almost equal but not so
convertable. The first example coming to mind being
complex numbers.

A secondary objection is that you are limited to
a very specific set of tolerances. If for instance
you want to verify that two numbers differ at most
by 0.0003 you can't specify that.

So I propose to add the following
def failUnlessNear(self, first, second, tolerance=1e-7, msg=None, norm=abs): """Fail if the two objects are too far appart as determined
by the distance between them and the tolerance allowed.
"""
if norm(second-first) > tolerance:
raise self.failureException, \
(msg or '%s != %s within %s tolerance' % (`first`, `second`, `tolerance`))

--
Antoon Pardon
How about a more general solution? E.g., how about an optional keyword arg
cmp=comparison_function
passed to failUnlessAlmostEqual? (I'm guessing here, no time to look at

it) E.g., that way for mixed numbers including complex you could (if you thought it made sense, which I am not necessarily arguing ;-) use e.g.

def special_cmp(x,y): # untested!
diff = complex(x)-complex(y)
return max(cmp(abs(diff.real), tolerance), cmp(abs(diff.imag), tolerance))
and pass cmp=special_cmp as the kwarg.

For special objects, you could define other kinds of nearness, and raise
appropriate informative exceptions if you get non-comparable arguments.

(obviously tolerance has to be defined, so if you want to vary it conveniently, you could pass it to a factory function that does the above def and returns it with tolerance captured in a closure referred to by special_cmp).

Or some other way. The point is you get to define the cmp= function as you please without modifying the framework (once the optional kwarg is implemented).)
I think this is overkill. I find myself using a raw assert much of the time
rather than unittest's specific test methods; it works just as well and I
don't have to remember the blasted syntax!

The only reason for doing float and complex specially is that they are
basic Python types, and while it's trivial to do the correct floating point
test (assert abs(x - y) < tolerance) in each instance, it's repetitive code
that isn't that easy to generalize correctly (at least without having to
specify the tolerance on each call). See my other response for the
general solution I used in FIT.

John Roth
gotta go...

Regards,
Bengt Richter

Jul 18 '05 #5
[John Roth]
I think this is overkill. I find myself using a raw assert much of the time
rather than unittest's specific test methods; it works just as well and I
don't have to remember the blasted syntax!


It doesn't work as well, because assert stmts "vanish" when running
tests with -O. Luckily,

self.assert_(expression)

works fine in a unittest, with or without -O.

self.assertEqual(e1, e2)

is usually a lot better than

self.assert_(e1 == e2)

too, because the former displays the unequal values when it fails.
Jul 18 '05 #6
Op 2004-07-19, Jeff Epler schreef <je****@unpythonic.net>:

--8/UBlNHSEJa6utmr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Jul 19, 2004 at 11:06:47AM +0000, Antoon Pardon wrote:
I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.
I'd like to hear more about the uses you envision about this,


It can be used with every vectorspace that defines a distance
between vectors.

If someone wants to implement quaternions, he can use this
method to test whether the result is close enough to
what it should be.

Same with vectors or simple complex calculations.
and
especially about how to choose "tolerance" properly.


Sorry, but that would require a course in numerical
analysis.

--
Antoon Pardon
Jul 18 '05 #7
Op 2004-07-19, John Roth schreef <ne********@jhrothjr.com>:
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.

My main problem is, that it is only usefull with objects
that can be converted to floats, while there are a whole
bunch of objects that can be almost equal but not so
convertable. The first example coming to mind being
complex numbers.

A secondary objection is that you are limited to
a very specific set of tolerances. If for instance
you want to verify that two numbers differ at most
by 0.0003 you can't specify that.
Float and complex have two very different issues.


Only if you want them to be. Floats are a subset
of complex and as such can be treated exactly
the same.
Since I'm maintaining the Python port of FIT, I
had to deal with them. What I did for float was
use the character form of the float to determine
the precision. The default routine appends a
character 5 and then uses this to calculate the
bounds within which the other value must be found.

An example may help. Let's say I want to
test against '6.23e14'. This method would
establish bounds of 6.235e14 and 6.225e14
and then test whether the other number was
within those bounds. (Note that the '5' is
appended before the numbers are converted
to float, however the second bound is calculated
after the conversion.)
Why don't you just test whether the second
number lies within a fault tolerance of
5e11 of 6.23e14
There's also a way of prescribing something other
than '5' to append. This approach is due to
Ward Cunningham; what I did was move it
from the ScientificDouble class to the base
float type adapter. (The Java source can be
located in a number of places, including
fit.c2.com and www.fitnesse.org. The Python
source is in the files section of the Extremeprogramming
and fitnesse Yahoo groups. You're welcome
to copy the approach, but since Ward put it
under the GPL, I don't think it can be directly
dropped into unittest.)

Complex, on the other hand, should be dealt
with by calculating the distance between the
two values in the i,j plane
and then seeing if this distance is within a given
bound. The bound should, of course, be a
separately specifiable parameter.
There is no reason floats should be treated differently.
If you want to, be my guest, but there really is no
need, and doing so when you are working with both
just complicates things needlessly.
One major issue is that these are very type specific;
the methods should be called something like
"failUnlessFloatWithinTolerance" and
"failUnlessComplexWithinTolerance".


Why? calculating the distance between numbers and
checking whether this distance is within bounds
works just as good for floats as it does for
complex numbers. We don't need an absForFloat
and an absForComplex either. So why do you want
to split this up?

--
Antoon Pardon
Jul 18 '05 #8
In article <sl*******************@trout.vub.ac.be>,
Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
Only if you want them to be. Floats are a subset
of complex and as such can be treated exactly
the same.


Why do you say floats are a subset of complex? There's a reasonable
argument that could be made that int/float and scalar/complex are
orthogonal properties. No reason why you shouldn't be able to have a
set of numbers which are 2-tuples with real and imaginary parts, each of
which has an integral value. The set would, I believe, be closed for
the same operations that integers are (addition, subtraction, and
multiplication).

Of course, I'm talking theoretically. In the current Python, complex
numbers do indeed appear to have floating point components.
Jul 18 '05 #9
Piggy backing.

Op 2004-07-19, John Roth schreef <ne********@jhrothjr.com>:
"Bengt Richter" <bo**@oz.net> wrote in message
news:cd**********@216.39.172.122@theriver.com...
On 19 Jul 2004 11:06:47 GMT, Antoon Pardon <ap*****@forel.vub.ac.be>

wrote:
>I have been working with unittests lately and found that the
>self.failUnlessAlmostEqual, isn't as usefull as it could be.
>
>My main problem is, that it is only usefull with objects
>that can be converted to floats, while there are a whole
>bunch of objects that can be almost equal but not so
>convertable. The first example coming to mind being
>complex numbers.
>
>A secondary objection is that you are limited to
>a very specific set of tolerances. If for instance
>you want to verify that two numbers differ at most
>by 0.0003 you can't specify that.
>
>So I propose to add the following
>
>
> def failUnlessNear(self, first, second, tolerance=1e-7, msg=None, norm=abs):
> """Fail if the two objects are too far appart as determined
> by the distance between them and the tolerance allowed.
> """
> if norm(second-first) > tolerance:
> raise self.failureException, \
> (msg or '%s != %s within %s tolerance' % (`first`, `second`, `tolerance`))
>
>
>--
>Antoon Pardon


How about a more general solution? E.g., how about an optional keyword arg
cmp=comparison_function
I think the ability to define a norm, being the length of the number,
vector or other entities is all that is needed. The reason I think so is that
mathematcally, the norm of a vector and the distance between two vectors
are closely linked. The norm of a vector is the distance between this
vector and the null vector and the distance between two vectors is the
norm of the difference vector.

We could of course leave this relationship behind, but then I think
providing a distance function is enough, something like the following
should suffice.

def failUnlessNear(self, first, second, tolerance=1e-7, msg=None,
distance=lambda x,y :abs(x-y)):
"""Fail if the two objects are too far appart as determined
by the distance between them and the tolerance allowed.
"""
if distance(second,first) > tolerance:
raise self.failureException, \
(msg or '%s != %s within %s tolerance' % (`first`, `second`, `tolerance`))
passed to failUnlessAlmostEqual? (I'm guessing here, no time to look at it)
E.g., that way for mixed numbers including complex you could (if you thought
it made sense, which I am not necessarily arguing ;-) use e.g.

def special_cmp(x,y): # untested!
diff = complex(x)-complex(y)
return max(cmp(abs(diff.real), tolerance), cmp(abs(diff.imag), tolerance))

and pass cmp=special_cmp as the kwarg.
I'm sorry but I have a hard time figuring out what you want to do here.
First of all, your special_cmp normally has no access to the tolerance.
So either you want a third parameter or you are mixing things that
should go in special_cmp with things you want to happen in
failUnlessNear. Using my distance approach, I think you wanted this:

def dist(x,y):

diff = complex(x)-complex(y)
return max(abs(diff.real) , abs(diff.imag))

For special objects, you could define other kinds of nearness, and raise
appropriate informative exceptions if you get non-comparable arguments.
Well I have a hard time imaganing a usefull distance function whose
results don't form a total order. If I have a tolerance t and an
actual distance d, but d and t don't compare then the question whether
the two objects are near enough is unanswerable.
(obviously tolerance has to be defined, so if you want to vary it conveniently,
you could pass it to a factory function that does the above def and returns
it with tolerance captured in a closure referred to by special_cmp).

Or some other way. The point is you get to define the cmp= function as you please
without modifying the framework (once the optional kwarg is implemented)


Well mostly I'm all for choosing the more general solution. But in this
case I sure would like to know if you have an actual example in mind.

The reason I ask is that this is stuff that comes from mathematics and
this is AFAIK a general framework that is used for distances on all
kind of mathematical objects. I can of course be ignorant of a more
general framework in mathematics to deal with this and of course it
is possible that a more general approach is usefull although it hasn't
caught the interest of the mathematical community, that is why I ask
for an example.

--
Antoon Pardon
Jul 18 '05 #10
Op 2004-07-20, Roy Smith schreef <ro*@panix.com>:
In article <sl*******************@trout.vub.ac.be>,
Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
Only if you want them to be. Floats are a subset
of complex and as such can be treated exactly
the same.
Why do you say floats are a subset of complex?


because if x is a float it is equal to x + 0j.

So whatever algorithm you use to see whether
two complex numbers a and b are near enough,
you can use that same algorithm to see whether
two floats f and g are near enough by using
f + 0j and g + 0j for a and b.

more specifically you can use the test:

abs(a - b) < tolerance.

for complex numbers as well as floats, and
for every numberlike object you wish to
define that has a __sub__ and an __abs__
method.
There's a reasonable
argument that could be made that int/float and scalar/complex are
orthogonal properties. No reason why you shouldn't be able to have a
set of numbers which are 2-tuples with real and imaginary parts, each of
which has an integral value. The set would, I believe, be closed for
the same operations that integers are (addition, subtraction, and
multiplication).


Indeed no reason, but you wouldn't call them complex and I would
call the integers a subset of these defined numbers for the same
reason as I called the floats a subset of complex.

--
Antoon Pardon
Jul 18 '05 #11
> Op 2004-07-19, Jeff Epler schreef <je****@unpythonic.net>:
and especially about how to choose "tolerance" properly.

On Tue, Jul 20, 2004 at 07:32:53AM +0000, Antoon Pardon wrote: Sorry, but that would require a course in numerical
analysis.


Oh, that's too bad. I bet this will end up being misused by a lot of
pepole, then, because few of us have had courses in numerical analysis.

Oh well, as long as it's there for you and for Tim Peters, I guess it's
no loss for the rest of us.

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFA/QiwJd01MZaTXX0RAhfzAKCZU7M1+QheQzdV1cW93oz2Z9H9sQC bByjG
xP45gdjQyPDeSz8ruSW5MLs=
=I90K
-----END PGP SIGNATURE-----

Jul 18 '05 #12
Op 2004-07-20, Jeff Epler schreef <je****@unpythonic.net>:

--TB36FDmn/VVEgNH/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Op 2004-07-19, Jeff Epler schreef <je****@unpythonic.net>:
> and especially about how to choose "tolerance" properly.


On Tue, Jul 20, 2004 at 07:32:53AM +0000, Antoon Pardon wrote:
Sorry, but that would require a course in numerical
analysis.


Oh, that's too bad. I bet this will end up being misused by a lot of
pepole, then, because few of us have had courses in numerical analysis.


Well then I suspect that assertAlmostEqual, is being missued by a lot
of people, because properly choosing the right number of places to round to,
is about the same difficulty as properly choosing a tolerance.

--
Antoon Pardon
Jul 18 '05 #13
Tim Peters <ti********@gmail.com> writes:
[John Roth]
I think this is overkill. I find myself using a raw assert much of the time
rather than unittest's specific test methods; it works just as well and I
don't have to remember the blasted syntax!
It doesn't work as well, because assert stmts "vanish" when running
tests with -O. Luckily,

self.assert_(expression)

works fine in a unittest, with or without -O.

self.assertEqual(e1, e2)

is usually a lot better than

self.assert_(e1 == e2)

too, because the former displays the unequal values when it fails.


Have you seen Holger Krekel's utest?

$ cat test.py
def test_something():
assert "abc"[::-1] == "cab"
$ python2.3 ./std/bin/utest test.py
inserting /home/mwh/src/pypy
__________________________________________________ _____________________________
______________________________ TESTS STARTING ______________________________
__________________________________________________ _____________________________
F

__________________________________________________ _____________________________
________________________________ Test Failure ________________________________
test_something
'/home/mwh/src/pypy/test.py', line 2


def test_something(): assert "abc"[::-1] == "cab"


-------------------------------------------------------------------------------
assert 'cba' == 'cab'
============================== 1 TESTS FINISHED ==============================
0.06 seconds (0 passed, 1 failed, 0 skipped)

Doesn't seem to be the easiest to install package I've ever used,
mind...

Cheers,
mwh

--
8. A programming language is low level when its programs require
attention to the irrelevant.
-- Alan Perlis, http://www.cs.yale.edu/homes/perlis-alan/quotes.html
Jul 18 '05 #14
Michael Hudson <mw*@python.net> writes:
Have you seen Holger Krekel's utest?

[...]

Nice!
Does it support ruuning test cases in a separate process? That's what
I currently need, and currently implementing on top of unittest...

Thomas
Jul 18 '05 #15
Thomas Heller <th*****@python.net> writes:
Michael Hudson <mw*@python.net> writes:
Have you seen Holger Krekel's utest?

[...]

Nice!
Does it support ruuning test cases in a separate process? That's what
I currently need, and currently implementing on top of unittest...


I don't know but I doubt it.

Cheers,
mwh

--
<dash> moshez: you aren't making sense now
<moshez> dash: *now*? I'm not making sense *now*?
-- from Twisted.Quotes
Jul 18 '05 #16
"Tim Peters" <ti********@gmail.com> wrote in message
news:ma*************************************@pytho n.org...
[John Roth]
I think this is overkill. I find myself using a raw assert much of the time rather than unittest's specific test methods; it works just as well and I don't have to remember the blasted syntax!


It doesn't work as well, because assert stmts "vanish" when running
tests with -O.


I'm not sure why I'd ever want to bother compiling
my test modules with -O. (In fact, I'm not sure what
-O does any more. I'm sure it does something besides
removing asserts, but I don't know what.)

John Roth

Jul 18 '05 #17
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
Op 2004-07-19, John Roth schreef <ne********@jhrothjr.com>:
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
I have been working with unittests lately and found that the
self.failUnlessAlmostEqual, isn't as usefull as it could be.

My main problem is, that it is only usefull with objects
that can be converted to floats, while there are a whole
bunch of objects that can be almost equal but not so
convertable. The first example coming to mind being
complex numbers.

A secondary objection is that you are limited to
a very specific set of tolerances. If for instance
you want to verify that two numbers differ at most
by 0.0003 you can't specify that.
Float and complex have two very different issues.


Only if you want them to be. Floats are a subset
of complex and as such can be treated exactly
the same.


Floats are not a subset of complex. I concur
with Roy Smith's comments on that issue. There's
no reason why complex numbers cannot be
represented by a pair of integers, or rationals,
or the new floating decimal type, or whatever.

In addition, you're going to have to do significant
type checking if you want to combine floats and
complex in the same method call. That's just
poor design.
Since I'm maintaining the Python port of FIT, I
had to deal with them. What I did for float was
use the character form of the float to determine
the precision. The default routine appends a
character 5 and then uses this to calculate the
bounds within which the other value must be found.

An example may help. Let's say I want to
test against '6.23e14'. This method would
establish bounds of 6.235e14 and 6.225e14
and then test whether the other number was
within those bounds. (Note that the '5' is
appended before the numbers are converted
to float, however the second bound is calculated
after the conversion.)


Why don't you just test whether the second
number lies within a fault tolerance of
5e11 of 6.23e14


I take it you've never worked with FIT. It's intended
to be used by non-technical people on a project, such
as the on-site customer, business analysts and so forth.
If I did something as silly as requiring them to insert
a tolerance that is blatently obvious to anyone looking
at the number involved, I'd get a change request so fast
that the edges would char from the friction.

It would also violate the interface agreement that all
ports of FIT are supposed to conform to.

John Roth
--
Antoon Pardon

Jul 18 '05 #18
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
Op 2004-07-19, John Roth schreef <ne********@jhrothjr.com>:

An example may help. Let's say I want to
test against '6.23e14'. This method would
establish bounds of 6.235e14 and 6.225e14
and then test whether the other number was
within those bounds. (Note that the '5' is
appended before the numbers are converted
to float, however the second bound is calculated
after the conversion.)
Why don't you just test whether the second
number lies within a fault tolerance of
5e11 of 6.23e14


For one blatently obvious reason. It's harder
to calculate that in the character form than it
is to insert the '5', and you don't have the
information to tell what you wanted if you
convert from character to float first.

My objective here is to ***not have to***
separately enter a precision. The semantics
of saying I want something to be treated as equal
if it's "close enough" to 6.23e14 is that it should
be closer to that than to either 6.24e14 or
6.22e14.

John Roth

--
Antoon Pardon

Jul 18 '05 #19
On Tue, 20 Jul 2004, John Roth wrote:
In addition, you're going to have to do significant
type checking if you want to combine floats and
complex in the same method call. That's just
poor design.


Why would you have to do that? The Python operators, as well as every
function in cmath, transparently support both floats and complex numbers
(as they should). Every operation between floats and complex numbers is
well-defined.

Jul 18 '05 #20

"Christopher T King" <sq******@WPI.EDU> wrote in message
news:Pi*************************************@ccc8. wpi.edu...
On Tue, 20 Jul 2004, John Roth wrote:
In addition, you're going to have to do significant
type checking if you want to combine floats and
complex in the same method call. That's just
poor design.
Why would you have to do that? The Python operators, as well as every
function in cmath, transparently support both floats and complex numbers
(as they should). Every operation between floats and complex numbers is
well-defined.


Because the "distance" between two floats is

abs(a - b)

while the "distance" between two complex numbers

is something like

math.sqrt(diff.real ** 2 + diff.imag ** 2)

This requires a type check to differentiate which
formula you need to use.

John Roth

Jul 18 '05 #21
[John Roth]
In addition, you're going to have to do significant
type checking if you want to combine floats and
complex in the same method call. That's just
poor design.
[Christopher T King]
Why would you have to do that? The Python operators, as well as every
function in cmath, transparently support both floats and complex numbers
(as they should). Every operation between floats and complex numbers is
well-defined.

[John] Because the "distance" between two floats is

abs(a - b)

while the "distance" between two complex numbers

is something like

math.sqrt(diff.real ** 2 + diff.imag ** 2)

This requires a type check to differentiate which
formula you need to use.


Nope. abs(a - b) works for both cases, although for complex numbers
Python uses a numerical method less prone to spurious
overflow/underflow than the "square root of the sum of the squares"
formula.
abs((12+29j) - (9+25j)) 5.0


which = sqrt((12-9)**2 + (29-25)**2) = sqrt(3**2 + 4**2) = sqrt(9 +
16) = sqrt(25).

Note that if the difference in the imaginary components is 0, the
formula reduces to

math.sqrt(diff.real**2)

which = |diff.real|. IOW, the definition of real abs() is a special
case of the definition of complex abs().
Jul 18 '05 #22
"Tim Peters" <ti********@gmail.com> wrote in message
news:ma*************************************@pytho n.org...

Nope. abs(a - b) works for both cases, although for complex numbers
Python uses a numerical method less prone to spurious
overflow/underflow than the "square root of the sum of the squares"
formula.
I didn't know that. It does make sense to do something like
that, but it seems a bit like deep magic to make abs
recognize that the operand is a subtraction.

John Roth

Jul 18 '05 #23
[Tim Peters]
Nope. abs(a - b) works for both cases, although for complex numbers
Python uses a numerical method less prone to spurious
overflow/underflow than the "square root of the sum of the squares"
formula.

[John Roth] I didn't know that. It does make sense to do something like
that, but it seems a bit like deep magic to make abs
recognize that the operand is a subtraction.


That would be deep magic indeed! But that doesn't happen. abs(x)
works on "a number". Regardless of whether a and b are float or
complex or integer or a mix, abs(a-b) first subtracts b from a, then
passes the difference to abs().
Jul 18 '05 #24

"Tim Peters" <ti********@gmail.com> wrote in message
news:ma*************************************@pytho n.org...
[Tim Peters]
Nope. abs(a - b) works for both cases, although for complex numbers
Python uses a numerical method less prone to spurious
overflow/underflow than the "square root of the sum of the squares"
formula.


[John Roth]
I didn't know that. It does make sense to do something like
that, but it seems a bit like deep magic to make abs
recognize that the operand is a subtraction.


That would be deep magic indeed! But that doesn't happen. abs(x)
works on "a number". Regardless of whether a and b are float or
complex or integer or a mix, abs(a-b) first subtracts b from a, then
passes the difference to abs().


Is that how complex subtraction works? I thought it produced
a complex, and your answers seem to say it produces a real.
Obviously, my mathematical background isn't giving me the
same answers it's giving you.

John Roth
Jul 18 '05 #25
[John Roth trying hard to confuse himself :-)]

Here's another perspective: abs(x) is ignorant of the class of x. Like
len(), it just calls the corresponding special method which does the
appropriate thing -- max(x, -x) for float, sqrt(x.real**2 + x.imag**2) for
complex -- or something theoretically equivalent, but better suited to the
limitations of numerical mathematics.
class s(str): .... def __abs__(self):
.... return self.upper()
.... abs(s("so what")) 'SO WHAT'


Peter

Jul 18 '05 #26
"John Roth" <ne********@jhrothjr.com> wrote:
Because the "distance" between two floats is

abs(a - b)

while the "distance" between two complex numbers

is something like

math.sqrt(diff.real ** 2 + diff.imag ** 2)


The distance between two complex numbers is indeed computed using the
pythagorean formula, but all that is hidden from view when you just say
"abs (a - b)".
import math
a = 1 + 3j
b = -3 + 1j
math.sqrt ((a.real - b.real) ** 2 + (a.imag - b.imag) ** 2) 4.4721359549995796 abs (a-b)

4.4721359549995796
Jul 18 '05 #27
In article <10*************@news.supernews.com>,
"John Roth" <ne********@jhrothjr.com> wrote:
"Tim Peters" <ti********@gmail.com> wrote in message
news:ma*************************************@pytho n.org...

Nope. abs(a - b) works for both cases, although for complex numbers
Python uses a numerical method less prone to spurious
overflow/underflow than the "square root of the sum of the squares"
formula.


I didn't know that. It does make sense to do something like
that, but it seems a bit like deep magic to make abs
recognize that the operand is a subtraction.

John Roth


It's not deep magic at all. It's just the normal rules of complex math.
Jul 18 '05 #28
[John Roth]
Is that how complex subtraction works? I thought it produced
a complex,
That's right.
and your answers seem to say it produces a real.


No, complex.__abs__() produces a float. Every type is free to
implement __abs__ in any way it likes. complex.__abs__ is implemented
as if by

class complex:
...
def __abs__(self):
import math
return math.hypot(self.real, self.imag)

In the same way, every type is free to implement __sub__ in any way it
likes, which is why infix "-" can also do a different thing for
complex operands than for float operands.

BTW, abs() itself is implemented as if by

def abs(x):
return x.__abs__()
Jul 18 '05 #29
John Roth <ne********@jhrothjr.com> wrote:
"Christopher T King" <sq******@WPI.EDU> wrote in message
news:Pi*************************************@ccc8. wpi.edu...
On Tue, 20 Jul 2004, John Roth wrote:
In addition, you're going to have to do significant
type checking if you want to combine floats and
complex in the same method call. That's just
poor design.
Why would you have to do that? The Python operators, as well as every
function in cmath, transparently support both floats and complex numbers
(as they should). Every operation between floats and complex numbers is
well-defined.

Because the "distance" between two floats is abs(a - b) while the "distance" between two complex numbers is something like
is just the same: abs(a - b) it works for complex numbers
just as well as it does with floats. In fact it works for
any numberlike object that has __sub__ and __abs__ methods
defined.
math.sqrt(diff.real ** 2 + diff.imag ** 2)
This is just the definition for abs on complex numbers.
This requires a type check to differentiate which
formula you need to use.


No it doesn't.

--
Antoon Pardon
Jul 18 '05 #30
John Roth <ne********@jhrothjr.com> wrote:
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
Op 2004-07-19, John Roth schreef <ne********@jhrothjr.com>:
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
> I have been working with unittests lately and found that the
> self.failUnlessAlmostEqual, isn't as usefull as it could be.
>
> My main problem is, that it is only usefull with objects
> that can be converted to floats, while there are a whole
> bunch of objects that can be almost equal but not so
> convertable. The first example coming to mind being
> complex numbers.
>
> A secondary objection is that you are limited to
> a very specific set of tolerances. If for instance
> you want to verify that two numbers differ at most
> by 0.0003 you can't specify that.

Float and complex have two very different issues.
Only if you want them to be. Floats are a subset
of complex and as such can be treated exactly
the same. Floats are not a subset of complex. I concur
with Roy Smith's comments on that issue. There's
Yes they are.
no reason why complex numbers cannot be
represented by a pair of integers, or rationals,
or the new floating decimal type, or whatever.
I think this is getting sidetracked. This started
with a request for a better test to check whether
something is near enough something else. Since
all your alternatives give exact results you don't
need to test for nearness you test for equality.

So within this contexts where you can't calculate
things exactly floats are a subset of complex.
In addition, you're going to have to do significant
type checking if you want to combine floats and
complex in the same method call. That's just
poor design.
No you don't. Please explain why something like

abs(a - b) < tolerance

needs typechecking when a and b can be complex
numbers as well as floats
Since I'm maintaining the Python port of FIT, I
had to deal with them. What I did for float was
use the character form of the float to determine
the precision. The default routine appends a
character 5 and then uses this to calculate the
bounds within which the other value must be found.

An example may help. Let's say I want to
test against '6.23e14'. This method would
establish bounds of 6.235e14 and 6.225e14
and then test whether the other number was
within those bounds. (Note that the '5' is
appended before the numbers are converted
to float, however the second bound is calculated
after the conversion.)


Why don't you just test whether the second
number lies within a fault tolerance of
5e11 of 6.23e14

I take it you've never worked with FIT. It's intended
to be used by non-technical people on a project, such
as the on-site customer, business analysts and so forth.
If I did something as silly as requiring them to insert
a tolerance that is blatently obvious to anyone looking
at the number involved, I'd get a change request so fast
that the edges would char from the friction.


A tolerance is never blatantly obvious from looking
at the number involved. On a number like 6.23e14
the tolreance could be 5e11 or 3e12 in fact from
just looking at the number I would guess at a tolerace
of 1e12, in other words bounds between 6.22e14 and
6.24e14.

Besides you are mixing user interface and implementation.
There is nothing stopping you from inferring this obvious
tolerance and using it in your program. The fact that
the user just insered 6.23e14, doesn't stop you the
programmer to test whether a second number lies within
a fault tolerance of 5e11 of 6.23e14

--
Antoon Pardon
Jul 18 '05 #31
John Roth <ne********@jhrothjr.com> wrote:
"Antoon Pardon" <ap*****@forel.vub.ac.be> wrote in message
news:sl*******************@trout.vub.ac.be...
Op 2004-07-19, John Roth schreef <ne********@jhrothjr.com>:

An example may help. Let's say I want to
test against '6.23e14'. This method would
establish bounds of 6.235e14 and 6.225e14
and then test whether the other number was
within those bounds. (Note that the '5' is
appended before the numbers are converted
to float, however the second bound is calculated
after the conversion.)
Why don't you just test whether the second
number lies within a fault tolerance of
5e11 of 6.23e14

For one blatently obvious reason. It's harder
to calculate that in the character form than it
is to insert the '5', and you don't have the
information to tell what you wanted if you
convert from character to float first.
And by making it easier here you make it more
difficult for yourself later on because now
you need two different ways to see whether
two numbers are near enough depending on
whether you are working with floats or complex
numbers.
My objective here is to ***not have to***
separately enter a precision. The semantics
of saying I want something to be treated as equal
if it's "close enough" to 6.23e14 is that it should
be closer to that than to either 6.24e14 or
6.22e14.


But you don't follow this same procedure with complex
numbers. If you are working with complex numbers you
are prepared to check whether a number is within a
certain distance from another number. if you have

6.23e14 + 3.49e11j you can work with the same procedure
and test that your second number is within the rectangle
that lies between 6.235e14 and 6.225e14 on the real
axis and between 3.485j and 3.495j on the imaganary axis.

--
Antoon Pardon
Jul 18 '05 #32

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Will Stuyvesant | last post by:
I have a unittest testfile like this: ----------------------- test_mod.py --------------------- import sys sys.path.append('..') import unittest import mod class...
0
by: Remy Blank | last post by:
Ok, here we go. I added the possibility for tests using the unittest.py framework to be skipped. Basically, I added two methods to TestCase: TestCase.skip(msg): skips unconditionally...
1
by: Thomas Heller | last post by:
I'm trying to integrate some doctest tests with unittest. The tests must be exposed as one or more subclasses of unittest.TestCase, so I'm collecting them with a call to doctest.DocTestSuite(),...
41
by: Roy Smith | last post by:
I've used the standard unittest (pyunit) module on a few projects in the past and have always thought it basicly worked fine but was just a little too complicated for what it did. I'm starting a...
7
by: Jorgen Grahn | last post by:
I have a set of tests in different modules: test_foo.py, test_bar.py and so on. All of these use the simplest possible internal layout: a number of classes containing test*() methods, and the good...
3
by: David Vincent | last post by:
-----BEGIN PGP SIGNED MESSAGE----- Hello I'm hoping to get some insight into a situation that seems odd to me. My Python experience is limited; I've just started using the unittest module....
2
by: Oleg Paraschenko | last post by:
Hello, I decided to re-use functionality of "unittest" module for my purposes. More precisely, I have a list of folders. For each folder, code should enter to the folder, execute a command and...
0
by: Chris Fonnesbeck | last post by:
I have built the following unit test, observing the examples laid out in the python docs: class testMCMC(unittest.TestCase): def setUp(self): # Create an instance of the sampler...
1
by: Chris Fonnesbeck | last post by:
I have a module for which I am trying to code a unit test. However, when I run unittest.main(), I get: In : import PyMC In : PyMC.unittest.main() ...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.