Like most other languages, English include two types of numbers: cardinal numbers (such as one, two, three, and four) that are used in counting, and ordinal numbers (such as first, second, third, and fourth) that are used to indicate a position in a sequence. In numeric form, ordinals are usually indicated by writing the digits in the number, followed by the last two letters of the English word that names the corresponding ordinal. Thus, the ordinal numbers first, second, third, and fourth often appear in print as 1st, 2nd, 3rd, and 4th.
The general rule for determining the suffix of an ordinal can be defined as follows:
Numbers ending in the digit 1, 2, and 3, take the suffixes "st", "nd", and "rd", respectively, unless the number ends with the two- digit combination 11, 12, or 13. Those numbers, and any numbers not ending with a 1, 2, or 3, take the suffix "th".
Your task in this problem is to write a function ordinalForm(n) that takes an integer n and returns a string indicating the corresponding ordinal number. (Roberts ch 10, problem 9).
What it looks like:
/* File: ordinalForm.java
* -----------------
*This console program lets the user enter in any integer and will print out the ordinal form of that number. For example
*the ordinal form of 1 is "1st," 2 is "2nd" etc. The user enters the sentinel value "-1" to stop running the program.
*
*The program and the method of the same name takes an integer as the entered value and returns a string. We use the ACM library's (?)
*built-in Integer class and its toString method. Because the suffix of an ordinal value depends on the last digit
*of a number our program has to strip out and inspect the last digit of the supplied integer so we use the method
*"getLastDigit" to inspect the last digit. In the case of numbers ending with "11", "12" and "13" we need to see the last
**two* digits so we also use a similiarly-constructed getSecondToLastDigit.
*/
import acm.program.ConsoleProgram;
public class ordinalForm extends ConsoleProgram {
public void run() {
while (true){
int cardinal = readInt("Enter number and we'll give you the ordinal form: ");
if (cardinal == -1){
break;
}
print(makeOrdinal(cardinal));
}
}
private String makeOrdinal(int n) {
String ordinal = "";
int lastDigit = getLastDigit(n);
int secondToLastDigit = getSecondToLastDigit(n);
if ((lastDigit == 1) && secondToLastDigit !=(1)){
ordinal = Integer.toString(n) + "st"; //Not sure why it's "Integer.toString(n)" instead of "n.toString" or "toString(n)"
}
else if (lastDigit ==2 && secondToLastDigit !=(1)) {
ordinal = Integer.toString(n) + "nd";
}
else if (lastDigit == 3 && secondToLastDigit !=(1)) {
ordinal = Integer.toString(n) + "rd";
}
else ordinal = Integer.toString(n) + "th";
return ordinal;
}
private int getLastDigit(int n) {
int remainder = n % 10;
return remainder;
}
private int getSecondToLastDigit(int n) {
int remainder = 0;
for (int i = 0; i < 2; i++){
remainder = n % 10;
n /= 10;
}
return remainder;
}
}
}What made it tricky:
My first version of this was running just fine....it just kept returning the wrong answer. Have a look at this sample run when the bug existed and guess what the problem was:
Here's a clue: this is what my private methods getSecondToLastDigit(n) and getLastDigit(n) looked like:
private int getLastDigit(int n) {
int remainder = 0;
while (n > 0) {
remainder = n % 10;
n /= 10;
}
return remainder;
}
private int getSecondToLastDigit(int n) {
int remainder = 0;
while (n > 10) {
remainder = n % 10;
n /= 10;
}
return remainder;
}
So while getLastDigit(n) should have just divided by n *once* and returned the remainder, instead it kept dividing by n until there was nothing left. So it was really stripping off and returning the *first* digit, not the last! getSecondToLastDigit(n) was behaving the same way, except it stopped one iteration sooner so it returned the second digit, not the second-to-last. Ugh, so embarrassing, blame it on the Christmas food abundance.
I didn't see the pattern or understand what was wrong for a while so I made this quick debugging program that printed out the results of just getLastDigit(n):
import acm.program.ConsoleProgram;
public class testLastDigit extends ConsoleProgram {
public void run() {
int n = readInt("Enter an int and we'll give you the last digit");
print (getLastDigit(n));
}
private int getLastDigit(int n) {
int remainder = 0;
while (n > 0) {
remainder = n % 10;
n /= 10;
}
return remainder;
}
}
I ran it a bunch of times and saw that indeed, testLastDigit was giving me the wrong answer. Once I saw that it was wrong and predictably wrong, the fix was easy.

No comments:
Post a Comment