Reputation: 121
I am getting a value named amount
in an object through its getter as shown below.
Let's say the object is h
then
h.getAmount()
Now I need to develop a validator that will validate that amount
should be of type integer and if it is not then it will throw the exception, I have developed that also as shown below
private boolean isint (String amount){
boolean isValid = true;
try {
Integer.parseInt(amount);
}
catch(NumberFormatException e){
isValid = false;
}
return isValid;
}
Now the issue is that amount
coming from h
is an integer such as 1234
, but it can also be a float such as 1258.26
. So in the case of float it throws a NumberFormatException
.
How could I make it perfect for both the values whether it is integer or whether it is float?
Upvotes: 3
Views: 13388
Reputation: 50261
As suggested, it would be better to use long
and double
instead of int
and float
.
By the way, can't you simply check for a float
? If it is an int
, than it can always be a float
, potentially rounded with loss of precision.
public static boolean isFloat(String number){
try {
return !new Float(number).isNaN();
} catch (NumberFormatException e){
return false;
}
}
Running demo: https://ideone.com/UpGPsK
Output:
> 1234 IS a valid Integer or Float
> 1234.56 IS a valid Integer or Float
> 1234.56.78 IS NOT a valid Integer or Float
> abc IS NOT a valid Integer or Float
> 2147483647 IS a valid Integer or Float
> 3.4028235E38 IS a valid Integer or Float
> -2147483648 IS a valid Integer or Float
> 1.4E-45 IS a valid Integer or Float
Upvotes: 1
Reputation: 14164
If you're talking about integers or a few decimals, you're probably talking about money or quantities, for which BigDecimal is ideal; and floating-point not really so good (due to rounding errors).
Otherwise, you're talking about a double floating-point value.
new BigDecimal( str)
will parse an integer or decimal for you, but it will also accept exponents; eg 1.4E2 means 140.
Perhaps you want to use a regex pattern to validate it first;
if (! str.matches( "[-+]?(\\d+)|(\\d*\\.\\d+)"))
throw new NumberFormatException();
This pattern accepts decimals without any leading digits, such as .14159 -- which should be allowable.
Upvotes: 0
Reputation: 45070
You could use a regex
like this:-
if (str.matches("[-+]?[0-9]*\\.?[0-9]+")) { // You can use the `\\d` instead of `0-9` too!
// Is a number - int, float, double
}
[-+]? - For the sign.
[0-9]*\.?[0-9]+ - For the numbers and the decimal point between them.
Update:-
In case exponential needs to be handled too, then the below regex
can be used.
String regex = "[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?";
Upvotes: 3
Reputation: 22271
First of all, if you have a function called isInt
it should do exactly that -- check if it's an integer. No more and no less.
You could try something like that
enum VarType {
INTEGER, FLOAT, STRING, EMPTY
}
private VarType getVarType(String amount){
if (amount.length() ==0) {
return VarType.EMPTY;
}
if (amount.contains(".")) {
try {
Float.parseFloat(amount);
}
catch(NumberFormatException e){
return ValType.STRING;
}
return ValType.FLOAT;
} else {
try {
Integer.parseInt(amount);
}
catch(NumberFormatException e){
return ValType.STRING;
}
return ValType.INTEGER;
}
}
I would not recommend it though, because using exceptions in this way is really expensive. Exceptions should be used as their name suggests, to handle special cases, exceptions, and not as a standard flow.
I would do it like this:
public class ParseVarTest {
static enum VarType {
INTEGER, FLOAT, STRING, EMPTY
}
private static VarType getVarType(String amount){
boolean onlyDigits = true;
int dotCount = 0;
if (amount == null) {
return VarType.EMPTY;
}
String trimmed = amount.trim();
if (trimmed.length() == 0) {
return VarType.EMPTY;
}
int a=0;
if (trimmed.charAt(0) == '-') {
a++;
}
for (int max=trimmed.length(); a<max; a++) {
if ( trimmed.charAt(a) == '.' ) {
dotCount++;
if (dotCount>1) break;
} else if ( !Character.isDigit(trimmed.charAt(a)) ) {
onlyDigits = false;
break;
}
}
if (onlyDigits) {
if (dotCount ==0) {
return VarType.INTEGER;
} else if (dotCount ==1) {
return VarType.FLOAT;
} else {
return VarType.STRING;
}
}
return VarType.STRING;
}
public static void main(String[] args) {
String[] vars = {"", " ", "123", "-5123", "1234.41", "-1234.41", "-1234..41","a12312", "523sdf234sdf.123"};
for (String var: vars) {
System.out.print(var);
System.out.print(": \t");
System.out.println(getVarType(var));
}
}
}
It's quite long for such a simple task, but:
no regexes
at most a single scan of the string
readable (IMO)
fast
However, this solution does not validate the range of the value. String 10000000000
would still be recognized as a VarType.INTEGER
even though the value could not fit into an int
variable in Java.
Upvotes: 3
Reputation: 9721
Use Double.parseDouble ... (method name changed to isNumber
to better reflect the meaning of the method) ...
private boolean isNumber (String amount){
boolean isValid = true;
try {
Double.parseDouble(amount);
}
catch(NumberFormatException e){
isValid = false;
}
return isValid;
}
... and could simplify to ...
private boolean isNumber (String amount){
try {
Double.parseDouble(amount);
}
catch(NumberFormatException e){
return false;
}
return true;
}
Upvotes: 1