Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Comparisons

We'll look at the basic comparison operators. We'll also look at the partial evaluation rules of the logic operators to show how we can build more useful expressions. Finally, we'll look at floating-point equality tests, which are sometimes done incorrectly.

Basic Comparisons

We compare values with the comparison operators. These correspond to the mathematical functions of <, ≤, >, ≥, = and ≠. Conditional expressions are often built using the Python comparison operators: <, <=, >, >=, == and != for less than, less than or equal to, greater than, greater than or equal to, equal to and not equal to.

>>> 
p1=22./7.

>>> 
p2=355/113.

>>> 
p1

3.1428571428571428
>>> 
p2

3.1415929203539825
>>> 
p1 < p2

False
>>> 
p1 >= p2

True

When applying a comparison operator, we see a number of steps.

  1. Evaluate both argument values.

  2. Apply the comparison to create a boolean result.

    1. Convert both parameters to the same type. Numbers are converted to progressively longer types: plain integer to long integer to float to complex.

    2. Do the comparison.

    3. Return True or False.

We call out these three steps explicitly because there are some subtleties in comparison among unlike types of data; we'll come to this later when we cover sequences, mappings and classes in Part II, “Data Structures”. Generally, it doesn't make sense to compare unlike types of data. After all, you can't ask "Which is larger, the Empire State Building or the color green?"

Comparisons can be combined in Python, unlike most other programming languages. We can ask: 0 <= a < 6 which has the usual mathematical meaning. We're not forced to use the longer form: 0 <= a and a < 6 .

>>> 
3 < p1 < 3.2

True
>>> 
3 < p1 and p1 < 3.2

True

This is useful when a is actually some complex expression that we'd rather not repeat.

Also note that the preceding example had a mixture of integers and floating-point numbers. The integers were coerced to floating-point in order to evaluate the expressions.

Partial Evaluation

We can combine the logic operators, comparisons and math. This allows us to use comparisons and logic to prevent common mathematical blunders like attempting to divide by zero, or attempting to take the square root of a negative number.

For example, let's start with this program that will figure the average of 95, 125 and 132.

sum = 95 + 125 + 132
count = 3
average = float(sum)/count
print average

Initially, we set the variables sum and count. Then we compute the average using sum and count.

Assume that the statement that computes the average (average=...), is part of a long and complex program. Sometimes that long program will try to compute the average of no numbers at all. This has the same effect as the following short example.

sum, count = 0, 0
average = float(sum)/count
print average

In the rare case that we have no numbers to average we don't want to crash when we foolishly attempt to divide by zero. We'd prefer to have some more graceful behavior.

Recall from the section called “Truth and Logic” that the and operator doesn't evaluate the right-hand side unless the left-hand side is True. Stated the other way, the and operator only evaluates the right side if the left side is True. We can guard the division like this:

average = count != 0 and sum/count
print average

This is an example that can simplify certain kinds of complex processing. If the count is non-zero, the left side is true and the right side must be checked. If the count is zero, the left side is False, the result of the complete and operation is False.

This is a consequence of the meaning of the word and . The expression a and b means that a is true as well as b is true. If a is false, the value of b doesn't really matter, since the whole expression is clearly false. A similar analysis holds for the word or . The expression a or b means that one of the two is true; it also means that neither of the two is false. If a is true, then the value of b doesn't change the truth of the whole expression.

The statement “It's cold and rainy” is completely false when it is warm; rain doesn't matter to falsifying the whole statement. Similarly, “I'm stopping for coffee or a newspaper” is true if I've stopped for coffee, irrespective of whether or not I stop for a newspaper.

Floating-Point Comparisons

Exact equality between floating-point numbers is a dangerous concept. After a lengthy computation, round-off errors in floating point numbers may have infinitesimally small differences. The answers are close enough to equal for all practical purposes, but every single one of the 64 bits may not be identical.

The following technique is the appropriate way to do floating point comparisons.

abs(a-b)<0.0001

Rather than ask if the two floating point values are the same, we ask if they're close enough to be considered the same. For example, run the following tiny program.

Example 7.1. floatequal.py

#!/usr/bin/env python
# Are two floating point values really completely equal?
a,b = 1/3.0, .1/.3
print a,b,a==b
print abs(a-b)<0.00001

When we run this program, we get the following output

$ 

python floatequal.py

0.333333333333 0.333333333333 False
True
$ 

The two values appear the same when printed. Yet, on most platforms, the == test returns False. They are not precisely the same. This is a consequence of representing real numbers with only a finite amount of binary precision. Certain repeating decimals get truncated, and these truncation errors accumulate in our calculations.

There are ways to avoid this problem; one part of this avoidance is to do the algebra necessary to postpone doing division operations. Division introduces the largest number erroneous bits onto the trailing edge of our numbers. The other part of avoiding the problem is never to compare floating point numbers for exact equality.


 
 
  Published under the terms of the Open Publication License Design by Interspire