Books / Patterns for Beginning Programmers / Chapter 13
Digit Counting
There are many situations in which a program needs to know the number of
digits in an int
. Unfortunately, int
variables don’t have properties
other than their value. In other words, anthropomorphizing a little,
int
variables don’t know anything about themselves. This chapter
considers solutions to this problem given this observation.
In this chapter
Motivation
As you know from Chapter 4 on digit manipulation, in order to drop or extract digits from the left side of an integer, you needed to know the number of digits in the number. In the examples in that chapter, the number of digits was known. Unfortunately, that isn’t always the case. For example, credit card account numbers might have between six and nine digits. The problem, then, is that of determining the number of digits in a number.
Review
As you also know from Chapter 4 on digit manipulation, the position of a digit corresponds to a particular power of 10. Specifically, the digit in position \(n\) (counting from the right, starting with 0) corresponds to the \(10^n\)s place. For example, position \(2\) corresponds to the \(10^2\) or \(100\)s place. To count digits you need to be able to invert the process. For example, to count a three-digit number, you need to find the position that the \(100\)s place corresponds to.
As you hopefully recall, this is the domain of the logarithm. In a decimal (i.e., base 10) representation, the \(\log\_{10}(x)\) is often described as the value of \(n\) that \(10\) must be raised to in order to get \(x\). More formally, \(\log\_{10}(x)\) is the value of \(n\) that satisfies \(x = 10^n\). So, returning to our example, the position of the \(100\)s place corresponds to \(\log\_{10}(100)\), which is \(2\) (since \(10^2\) is \(100\)). More generally, \(\log\_{b}(x)\) is the value of \(n\) that satisfies \(x = b^n\), where \(b\) is referred to as the base (or radix) of the logarithm.
Thinking About The Problem
Evaluating \(\log\_{10}(x)\) can be quite difficult, in general. However, it is easy to find bounds. For example, since \(\log\_{10}(100)\) is \(2\) and \(\log\_{10}(1000)\) is \(3\) (and logarithms are monotonic) it follows that \(\log\_{10}(x)\) is in the interval \(\[2, 3)\) for any \(x \in \[100, 1000)\). This means that the \(\log\_{10}\) of any three-digit number is in \(\[2, 3)\) and that the \(\log\_{10}\) of any four-digit number is in \(\[3, 4)\). For example:
Math.log10(7198)
evaluates to approximately3.8572118423168926
which, as expected, is in the interval \(\[3, 4)\).Math.log10(462)
evaluates to approximately2.6646419755561257
which, as expected, is in the interval \(\[2, 3)\).Math.log10(10000)
evaluates to5.0
which, as expected, is in the interval \(\[5, 6)\).
The Pattern
More generally, the \(\log\_{10}\) of any
\(n\)-digit number will be in the interval
\(\[n-1, n)\), which means it will be greater than or
equal to \(n-1\) and strictly less than
\(n\). Hence, the integer part of
\(\log\_{10}\) of any \(n\)-digit number
will be \(n-1\). So, the number of digits in the number
x
is given by:
public static int digits(int x) {
return (int) Math.log10(x) + 1;
}
Examples
Returning to the credit card example, suppose that the account number is as follows:
cardNumber = 412831758;
Then, you can find the number of digits in the account number as follows:
n = digits(cardNumber);
Now, as you know from Chapter
4,
if you want to extract the left-most three digits (i.e., the issuer),
you need to drop the rightmost n - 3
digits. This involves dividing by
ten to the power of n-3
, which you can implement as follows:
issuer = cardNumber / (int) Math.pow(10.0, n - 3);
As another example, suppose you need to write a program for a newspaper that converts a dollar amount (e.g., a person’s annual income, the price of a house) into a phrase like “6 figures” or “7 figures”. You would again need to calculate the number of digits in the number of interest. So, for example, if you initialize the variable containing the annual income of the subject of the story as follows:
income = 156720;
you can then figure out the number of “figures” in that variable as follows:
figures = digits(income);
Looking Ahead
As with the digit manipulation pattern of Chapter 4, this pattern can be used with other representation schemes (i.e., other bases). All that is needed is to replace \(10\) with the desired base, \(b\).
Fortunately, it is easy to calculate the logarithm in one base given the
logarithm in another. That is, assuming you have the ability to
calculate \(\log\_{10}(x)\) (e.g., using Math.log10()
in Java):
whenever \(x \> 0\).
A Warning
Notice that the truncation pattern from Chapter
6
is not used in this pattern. Instead, typecasting is used to get the
integer part of the value returned by Math.log10()
. This is because
Math.log10()
returns a double
, and the truncation pattern is for
truncating integers.