Compound Numbers
A Programming Pattern
|
Prof. David Bernstein
James Madison University
|
|
Computer Science Department
|
bernstdh@jmu.edu
|
Motivation
- What is a Compound Number?
- A compound number is a quantity/measure that is
expressed in more than one unit
- Examples:
- Heights/lengths measured in miles, yards, feet and inches
- Weights measured in tons, pounds and ounces
- Times measured in hours, minutes and seconds
- Volumes measured in gallons, quarts, pints, ounces
Two Observations
- Individual Components:
- Are commonly integers (because parts of a whole are
usually denominated in different units)
- Arithmetic Operations:
The Obvious Implementation
- The Approach:
-
Have an attribute for each of the individual units (e.g.,
an
int
for pounds and an int
for ounces)
- Why it Seems Clever:
- A Continuing Example:
-
We have 3lbs,12oz of french fries and someone gives us more
or takes some away
The Continuing Example
- An Example of the Easiest Case:
- We have 3lbs,12oz of french fries and someone gives us
2oz more
- Processing this Specific Example:
- Processing this Kind of Example:
-
ounces = ounces + deltaounces;
The Continuing Example (cont.)
- An More Difficult Example:
- We have 3lbs,12oz of french fries and someone gives us
8oz more
- Processing:
-
pounds = pounds + (ounces + deltaounces) / 16;
ounces = (ounces + deltaounces) % 16;
- A Word of Caution:
-
The following code, while similar, is incorrect!
ounces = (ounces + deltaounces) % 16;
pounds = pounds + (ounces + deltaounces) / 16;
The Continuing Example (cont.)
- Increasing the Difficulty Further:
- We have 3lbs,12oz of french fries and someone gives us
5lbs,8oz more
- Processing:
-
pounds = (pounds + deltapounds) + (ounces + deltaounces) / 16;
ounces = (ounces + deltaounces) % 16;
The Continuing Example (cont.)
- Increasing the Difficulty Further:
- We have 1ton,1999lbs,12oz of french fries and someone gives us
8oz more
- Processing:
-
tons = (tons + deltatons) + (pounds + deltapounds + (ounces + deltaounces) / 16) / 2000;
pounds = (pounds + deltapounds) + (ounces + deltaounces) / 16;
ounces = (ounces + deltaounces) % 16;
The Continuing Example (cont.)
- Increasing the Difficulty Further:
- We have 1ton,1999lbs,12oz of french fries and someone gives us
1ton,200lbs,8oz more
- Increasing the Difficulty Further:
- We have 2tons,1999lbs,12oz of french fries and someone changes
the amount by -1ton,353lbs,-15oz
- Other Complications:
- Multiplication/division by a constant
- Ratios
- Sign (should all components have the same sign?)
- Comparisons (e.g.,
equals()
,
compareTo()
)
Learning from these Examples
- A Conclusion:
- It is possible to use the obvious implementation but there are
many ways/places that defects can be introduced
- A Hope:
- This situation has arisen frequently in the past and people
have developed a solution
A Better Implementation
- The Idea:
- Use a single attribute denominated in the "smallest" units
and convert when necessary
- The Continuing Example Revisited:
- Create a
Weight
class that has only one attribute
measured in ounces,
but accessors that can return tons, pounds and ounces and
mutators that can be passed tons, pounds, and ounces
A Better Implementation (cont.)
javaexamples/compoundnumbers/Weight.java
Don't Be Confused!
- A Common Misconception:
- The shortcomings of the obvious implementation arise
only if the objects are mutable
- The Reality:
- The shortcomings exist whenever operations are performed
on compound numbers (regardless of whether the object is mutable
or a new immutable object is created)
There's Always More to Learn