4.2 KiB
title, weight
| title | weight |
|---|---|
| SumDouble | 6 |
Below are some modifications to the code for deeper understanding of basic language constructions primarily data types. It is always advised to try completing them by yourself before reading the solution. Modifications progress in difficulty from easy to hard.
Task
- Input data is 64-bytes floating point numbers.
- Class should be named
SumDouble.
Solution
This modification is fairly easy. All we need to do is to replace all integers with floating point numbers.
Note
Here we can see all of the benefits of using
Character.isWhitespace(), because if we had had for example a set of digits and check if the character is in that set we would need to add.(point) to that set to count floating point numbers as well.
So here's the updated code
// SumDouble.java
public class SumDouble {
public static void main(String[] args) {
double sum = 0; // int -> double
for (String argument : args) {
StringBuilder number = new StringBuilder();
for (char c : argument.toCharArray()) {
if (!Character.isWhitespace(c)) {
number.append(c);
} else {
if (!number.isEmpty()) {
sum += Double.parseDouble(number.toString()); // Integer.parseInt -> Double.parseDouble())
}
number = new StringBuilder();
}
}
if (!number.isEmpty()) {
sum += Double.parseDouble(number.toString()); // Integer.parseInt() -> Double.parseDouble()
}
}
System.out.println(sum);
}
}
This code will work fine and pass all the tests, but can we improve it?
We can see repeating part of code here
if (!number.isEmpty()) {
sum += Double.parseDouble(number.toString()); // Integer.parseInt() -> Double.parseDouble()
}
And if we want to change it, we would need to do so in 2 places. That's considered bad practice. You can read about DRY principle here.
So let's extract this code to its own method called parseNumber.
static double parseNumber(StringBuilder number) {
return number.isEmpty() ? 0.0 : Double.parseDouble(number.toString());
}
It's a static method, because we can't call a non-static method from a static context which is main method. If we didn't have static keyword in parseNumber method we would have gotten an error.
$ javac SumDouble.java
SumDouble.java:13: error: non-static method parseNumber(StringBuilder) cannot be referenced from a static context
sum += parseNumber(number); // method call
^
SumDouble.java:18: error: non-static method parseNumber(StringBuilder) cannot be referenced from a static context
sum += parseNumber(number); // method call
^
2 errors
Also we need to discuss the ternary operator. It is a shortened form of if-statement. Its structure looks like this
(/* condition */) ? (/* do if true */) : (/* do if false */)
First argument states a condition. If the condition is true, then the second block gets executed. If the condition if false, then the third block gets executed. It will work the same as
if (/* condition */) {
/* do if true */
} else {
/* do if false */
}
So here's the updated code
// SumDouble.java
public class SumDouble {
public static void main(String[] args) {
double 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); // method call
number = new StringBuilder();
}
}
sum += parseNumber(number); // method call
}
System.out.println(sum);
}
static double parseNumber(StringBuilder number) {
return number.isEmpty() ? 0.0 : Double.parseDouble(number.toString());
}
}