Books / Patterns for Beginning Programmers / Chapter 6
Truncation
Integers commonly include more digits of accuracy than needed. In some situations, the right way to deal with this is using truncation. Truncation problems can be solved by dropping the right-most digits using the techniques from Chapter 4 on digit manipulation and then multiplying.
In this chapter
Motivation
Suppose you have to write a payroll program for a manufacturing company. The employees at the company get paid a fixed amount per piece, but only for multiples of ten pieces. For inventory purposes, the company keeps track of the exact number of pieces completed, but for payroll purposes, that number has more digits of accuracy than is needed. For example, if the employee completes 520 pieces, 521 pieces, or 529 pieces, they are going to be payed for 520 pieces. Hence, the payroll system you are writing must truncate the actual number of pieces produced to the second digit (i.e., the 10s place).
Review
If the person were being paid per completed batch of ten pieces (rather than per piece), then you would only need to determine the number of completed batches. Since there are 10 pieces per batch, you could accomplish this by dropping the right-most digit. Further, you know from the discussion of digit manipulation in Chapter 4 that this can be accomplished by dividing by \(10^1\) (using integer division).
For example, letting number
denote the actual number produced (at full
accuracy):
batches = number / 10;
where /
denotes integer division. So, an employee that completed 526
pieces completed 52 batches (ignoring the remaining 6 pieces).
Thinking About the Problem
Unfortunately, what you need is not the number of batches but, instead, the number of pieces truncated to the 10s place. Fortunately, given the number of batches, you can calculate this pretty easily. In particular:
truncated = batches * 10;
So, continuing with the example, the 52 batches corresponds to 520 units truncated to the 10s place.
The Pattern
It turns out that there’s nothing special about the 10s place, so the
general pattern is easy to see. Letting place
denote the integer place
to truncate to (i.e., 10
for the 10s place, 100
for the 100s place,
etc.), then the value truncated to that place is given by:
truncated = (number / place) * place;
where /
again denotes integer division.
One important aspect of this pattern is that it illustrates the
importance of not over-generalizing. In particular, at first glance, you
might think that the expression (number / place) * place
could be
simplified to number
. However, this is not the case when using integer
division. Specifically, when using integer division, (a / b) * b
only
equals a
when a
is evenly divisible by b
. For example, as
discussed above, (526 / 10) * 10
is equal to 52 * 10
or 520
, which
does not equal 526
.
Examples
Suppose you want to talk about something that will happen 87 years after
the year 1996. You might want to use the exact year (i.e., 1996 + 87
or 2083
), but you might want to know the decade or century rather than
the year. Truncating to the decade (i.e., a place
of 10
) using the
truncation pattern yields (2083 / 10) * 10
or 208 * 10
or 2080
.
Similarly, truncating to the century (i.e., a place
of 100
) using
the truncation pattern yields (2083 / 100) * 100
or 20 * 10
or
2000
.
Some Warnings
It’s important to note that people use the word “truncation” in a
variety of different, but related, ways. Most importantly, people often
talk about truncating floating point values to integer values (e.g.,
truncating 3.14
to 3
), which is commonly accomplished using a type
cast (e.g., (int)3.14
evaluates to 3
). Our concern here is with a
different notion of truncation.
It’s also important to distinguish between the accuracy used when performing calculations and the accuracy (or format) used when displaying output. In some situations it is necessary to perform calculations using truncated values. In other situations it is necessary to perform calculations using all of the digits of accuracy available and truncate at the end. In still other situations it is necessary to perform calculations using all of the digits of accuracy available and then format the output when it is displayed. It is your responsibility to know what is required of a particular section of code.