So at the input, a string contains different types of data. Basically, this is a string, int, and float. I check types through Float.parseFloat()
and Integer.parseInt()
. the Integer.parseInt()
works correctly, yet Float.parseFloat()
includes all the digits that are checked. How to avoid this?
The problem is that when checking for the float type, it also considers ints (output):
- Hello my 50 name 4.5 is James, I 20 years old and I have 5.7 coins
- Float 4
- Int 2
- String 12
public class TypeCountString {
public static void countTypeInString(String string){
String[] value = string.split(" ");
float ifFloat;
int ifInt;
String ifString;
int counter = 0;
// count Floats
for (String i: value){
try{
ifFloat = Float.parseFloat(i);
counter ;
continue;
} catch (NumberFormatException e){
}
}
System.out.println("Float " counter);
//count ints
counter = 0;
for (String i: value){
try{
ifInt = Integer.parseInt(i);
counter ;
continue;
} catch (NumberFormatException e){
}
}
System.out.println("Int " counter);
//counts strings
String stringOfStrings = string.replaceAll("[0-9.]","");
stringOfStrings = stringOfStrings.replaceAll(" "," ");
String[] value2 = stringOfStrings.split(" ");
System.out.println("String " value2.length);
}
public static void main(String[] args) {
String string = "Hello my 50 name 4.5 is James, I 20 years old and i have 5.7 coins";
System.out.println(string);
countTypeInString(string);
}
}
CodePudding user response:
As Integer is a sub-type of Float, Float will count in Integers into your float count. If you solely just want the number of float that is not integer, just take float count minus integer count.
CodePudding user response:
Some tokens (like "50") are parseable both as integer and float. Your code gives both of them a chance, even though your intention is to only count each token as one type or the other (so count "50" as an integer, not as a float).
A simple fix could be to modify your float check to be:
- make sure that
i
can passFloat.parseFloat()
, and - confirm that
i
contains a decimal point
That code edit could look like this:
Float.parseFloat(i);
if (i.contains(".")) {
counter ;
continue;
}
Or, as a more involved alternative, instead of checking all input tokens for floats, then re-checking all input tokens for integers, I would take a different approach.
First, I would change the code to stop checking the entire input string repeatedly. This is helpful for 2nd part below, but also cleans up an unnecessary inefficiency of re-checking tokens even if you've already identified their data type. If you had a large number of tokens, it's wasteful to try parsing all of them as float, then try all of them as integer, then try a third time to count plain strings.
Second, since you would be checking (and counting) each token only one time, you could:
- check for integer (before float) – if it passes
Integer.parseInt()
, increment that counter and move on to the next token - if it doesn't parse as integer, make an attempt to parse that token as float – just
Float.parseFloat()
without looking for decimal; if it worked then bump counter, move to next token - if it doesn't parse as integer or float, you know it's a
String
so simply bump the counter, then next token
CodePudding user response:
As others have already said, since int
is a subset of float
, you can always parse a string representing an int
as a float
, while the opposite is not true. In fact, if the parsing string contains a decimal separator and you attempt to parse it as an int
, you'll get a NumberFormatException
.
However, you could use this behavior to your advantage and try to parse each string to the data type with minimal representation (int
) and gradually increasing it as the parsing fails, until you reach the most generic representation (String
). In your case, you could start to parse each string to int
, if it fails proceed to float
and ultimately to String
if the float
parsing doesn't work either.
Here is a possible implementation:
public class Main {
public static void main(String[] args) {
countTypesInString();
}
public static void countTypesInString() {
String str = "Hello my 50 name 4.5 is James, I 20 years old and i have 5.7 coins";
String[] vetStr = str.split("\\s ");
List<Integer> listInt = new ArrayList<>();
List<Float> listFloat = new ArrayList<>();
List<String> listStr = new ArrayList<>();
for (String s : vetStr) {
try {
listInt.add(Integer.parseInt(s));
} catch (NumberFormatException exInt) {
try {
listFloat.add(Float.parseFloat(s));
} catch (NumberFormatException exFloat) {
listStr.add(s);
}
}
}
System.out.println("Number of ints: " listInt.size() " => " listInt);
System.out.println("Number of floats: " listFloat.size() " => " listFloat);
System.out.println("Number of strings: " listStr.size() " => " listStr);
}
}
Output
Number of ints: 2 => [50, 20]
Number of floats: 2 => [4.5, 5.7]
Number of strings: 12 => [Hello, my, name, is, James,, I, years, old, and, i, have, coins]
Side note: for real number representation, the double
type is a better choice. In fact, by default Java treats every literal representing a real number as a double
rather than a float
. In the snippet above I've kept using float
to maintain my code as close as possible to the original.