This commit is contained in:
261
content/courses/prog-intro/homeworks/sum/SumLongOctal/_index.md
Normal file
261
content/courses/prog-intro/homeworks/sum/SumLongOctal/_index.md
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
title: SumLongOctal
|
||||
weight: 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
|
||||
|
||||
```java
|
||||
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
|
||||
|
||||
```java
|
||||
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)`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#endsWith-java.lang.String-) method that checks if the string ends with `prefix`.
|
||||
|
||||
And also we change `16` to `8` here
|
||||
|
||||
```java
|
||||
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 variable `numberStringLength`, that represents a length of `numberString` (or number of characters in the string). Then, we take a substring using `substring(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 `- 1` and not `- 2` because last index is exclusive (meaning it doesn't count).
|
||||
|
||||
So the code for `parseNumber` method will be
|
||||
|
||||
```java
|
||||
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
|
||||
|
||||
```java
|
||||
// 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
|
||||
|
||||
```bash
|
||||
$ 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.
|
||||
|
||||
```java
|
||||
// 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 `sum` to `long` in order to store 64 bit numbers.
|
||||
|
||||
Let's test some more
|
||||
|
||||
```bash
|
||||
$ 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`](https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html) and more specifically we will be using its [`BigInteger.longValue()`](https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html#longValue--) method.
|
||||
|
||||
First we need to ***import*** it using
|
||||
|
||||
```java
|
||||
import java.math.BigInteger;
|
||||
```
|
||||
|
||||
and then we will replace
|
||||
|
||||
```java
|
||||
return Long.parseLong(numberString.substring(0, numberStringLength - 1), 8);
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```java
|
||||
return new BigInteger(number.substring(0, numberStringLength - 1), 8).longValue();
|
||||
```
|
||||
|
||||
So the final code would be
|
||||
|
||||
```java
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user