8.2 KiB
title, weight
| title | weight |
|---|---|
| SumLongOctal | 6 |
Task
- The input data is in 64 bit decimal numbers
- Octal numbers has suffix
"o" - Class should be named
SumLongOctal
Solution
We need to change our parseNumber method yet again. Let's take a look at it from SumHex modification
static long parseNumber(StringBuilder number) {
if (!number.isEmpty()) {
String numberString = number.toString();
if (
numberString.startsWith("0x") || numberString.startsWith("0X")
) {
return Long.parseLong(numberString.substring(2), 16);
} else {
return Integer.parseInt(numberString);
}
} else {
return 0;
}
}
Let's adapt our new logic on a concept level
static long parseNumber(StringBuilder number) {
if (!number.isEmpty()) {
String numberString = number.toString();
int numberStringLength = numberString.length();
if (
/* number is octal */
) {
return Long.parseLong(numberString.substring(0, numberStringLength - 1), 8); // 16 -> 8
} else {
return Integer.parseInt(numberString);
}
} else {
return 0;
}
}
As you can see is that we need to only change method of checking if the number is octal. It's actually fairly easy. With hexadecimal numbers we checked if the number started with "0x" or "0X". Now we need to check if the number ends with "o" or "O". To do that we will use String.endsWith(String suffix) method that checks if the string ends with prefix.
And also we change 16 to 8 here
return Long.parseLong(numberString.substring(0, numberStringLength - 1), 8);
Because we are converting from octal, not hexadecimal anymore.
Note
Note, that we alse changed how we crop out the last character of our
numberString. First, we introduced new variablenumberStringLength, that represents a length ofnumberString(or number of characters in the string). Then, we take a substring usingsubstring(0, numberStringLength - 1). We start at first index (0) and go all the way to the second from the end of the string. We use- 1and not- 2because last index is exclusive (meaning it doesn't count).
So the code for parseNumber method will be
static long parseNumber(StringBuilder number) {
if (!number.isEmpty()) {
String numberString = number.toString();
int numberStringLength = numberString.length();
if (
numberString.endsWith("o") || numberString.endsWith("O")
) {
return Long.parseLong(numberString.substring(0, numberStringLength - 1), 8); // 16 -> 8
} else {
return Integer.parseInt(numberString);
}
} else {
return 0;
}
}
So the solution would be
// SumLongOctal.java
public class SumLongOctal {
public static void main(String[] args) {
int sum = 0;
for (String argument : args) {
StringBuilder number = new StringBuilder();
for (char c : argument.toCharArray()) {
if (!Character.isWhitespace(c)) {
number.append(c);
} else {
sum += parseNumber(number);
number = new StringBuilder();
}
}
sum += parseNumber(number);
}
System.out.println(sum);
}
static long parseNumber(StringBuilder number) {
if (!number.isEmpty()) {
String numberString = number.toString();
int numberStringLength = numberString.length();
if (numberString.endsWith("o") || numberString.endsWith("O")) {
return Long.parseLong(numberString.substring(0, numberStringLength - ), 8);
} else {
return Integer.parseInt(numberString);
}
} else {
return 0;
}
}
}
Let's try to test it with test like this
$ java SumLongOctal " +12345678901234567 "
Exception in thread "main" java.lang.NumberFormatException: For input string: "+12345678901234567"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:778)
at sum.SumLongOctal.parseNumber(SumLongOctal.java:32)
at sum.SumLongOctal.main(SumLongOctal.java:15)
As you can see we got a NumberFormatException. Here it's not an octal number and it doesn't fit into int data type, so let's change int to long which is bigger.
// SumLongOctal.java
public class SumLongOctal {
public static void main(String[] args) {
long sum = 0; // int -> long
for (String argument : args) {
StringBuilder number = new StringBuilder();
for (char c : argument.toCharArray()) {
if (!Character.isWhitespace(c)) {
number.append(c);
} else {
sum += parseNumber(number);
number = new StringBuilder();
}
}
sum += parseNumber(number);
}
System.out.println(sum);
}
static long parseNumber(StringBuilder number) {
if (!number.isEmpty()) {
String numberString = number.toString();
int numberStringLength = numberString.length();
if (numberString.endsWith("o") || numberString.endsWith("O")) {
return Long.parseLong(numberString.substring(0, numberStringLength - 1), 8);
} else {
return Long.parseLong(numberString); // Integer.parseInt(...) -> Long.parseLong(...)
}
} else {
return 0;
}
}
}
Note
Notice we changed data type of
sumtolongin order to store 64 bit numbers.
Let's test some more
$ java SumLongOctal.java "1777777777777777777776o"
Exception in thread "main" java.lang.NumberFormatException: For input string: "1777777777777777777776" under radix 8
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Long.parseLong(Long.java:709)
at SumLongOctal.parseNumber(SumLongOctal.java:29)
at SumLongOctal.main(SumLongOctal.java:18)
We can see that this number doesn't fit into long data type. So we need to use something called BigInteger and more specifically we will be using its BigInteger.longValue() method.
First we need to import it using
import java.math.BigInteger;
and then we will replace
return Long.parseLong(numberString.substring(0, numberStringLength - 1), 8);
with
return new BigInteger(number.substring(0, numberStringLength - 1), 8).longValue();
So the final code would be
// SumLongOctal.java
import java.math.BigInteger;
public class SumLongOctal {
public static void main(String[] args) {
long sum = 0;
for (String argument : args) {
StringBuilder number = new StringBuilder();
for (char c : argument.toCharArray()) {
if (!Character.isWhitespace(c)) {
number.append(c);
} else {
sum += parseNumber(number);
number = new StringBuilder();
}
}
sum += parseNumber(number);
}
System.out.println(sum);
}
static long parseNumber(StringBuilder number) {
if (!number.isEmpty()) {
String numberString = number.toString();
int numberStringLength = numberString.length();
if (numberString.endsWith("o") || numberString.endsWith("O")) {
return new BigInteger(
number.substring(0, numberStringLength - 1),
8
).longValue();
} else {
return Long.parseLong(numberString);
}
} else {
return 0;
}
}
}