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?
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]+)?";
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.
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;
}
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
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.
Related
I'm trying to create Predicates to test Strings and determine the most appropriate variable type, which means I want to get the "smallest" numeric variable type that the parsed String fits into.
So for example, for a String "-1.2" the detected type should be float, but if the number exceeds the float range, it should detect double. If the number is even bigger, then BigDecimal.
For non-floating point numbers my tests seem to work fine,
but the decimal numbers are giving me more headaches than they should.
This is my isFloat test:
Predicate<String> isFloat =
s -> {
try {
Double d = Double.parseDouble(s);
return d >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
} catch (Exception e) {
return false;
}
};
String minOfFloat = String.valueOf(-Float.MAX_VALUE);
System.out.println(minOfFloat);
System.out.println(Double.parseDouble(minOfFloat));
System.out.println(isFloat.test(minOfFloat));
Outputs:
-3.4028235E38
-3.4028235E38
false //WHYYYYY
Similarly my next test would be to check if the number fits a double, and if not, return "BigDecimal".
What's the correct way to test this?
EDIT: This is the way I'm doing it, accepted answer brought me there:
public static final Predicate<String> isFloat =
s -> {
try {
Double d = Double.parseDouble(s);
return d.floatValue() >= -Float.MAX_VALUE
&& d.floatValue() <= Float.MAX_VALUE
&& !Float.isInfinite(d.floatValue())
&& !Float.isNaN(d.floatValue());
} catch (Exception e) {
return false;
}
};
Change your predicate to compare with d.floatValue() >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
In case, if your double value exceeds float range d.floatValue() returns infinity so you should be good with the change
Predicate<String> isFloat = s -> {
try {
Double d = Double.parseDouble(s);
return d.floatValue() >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
} catch (Exception e) {
return false;
}
};
String maxDouble = String.valueOf(Double.MAX_VALUE);
System.out.println(maxDouble);
System.out.println(isFloat.test(maxDouble));
Using BigDecimal is recomended when widening primitive conversion will be applied. I couldn't find a good duplicate, but see this posts
how-to-compare-correctly-long-and-float-primitives
comparing-float-and-double-primitives-in-java
to understand why you might get wrong results when comparing two different types. So I would do something like:
Predicate<String> isFloat =
str -> new BigDecimal(str).compareTo(new BigDecimal(String.valueOf(Float.MAX_VALUE))) <= 0 &&
new BigDecimal(str).compareTo(new BigDecimal(String.valueOf(-Float.MAX_VALUE))) >= 0;
For a homework assignment I'm working on you're required to create a custom LinkedList data structure to hold the terms of a polynomial. I'm having a problem at the moment with my constructor adding terms to the data structure because it needs to accept a string like "5.2 3 2.1 2" (which would be the equivalent of 5.2^3 + 2.1^2) and store it in the my custom LinkedList. Some of the requirements include that terms cannot have coefficients of zero, exponents must be integers, and coefficients can be either integers or doubles. When I trace the program using my IDE's debugger what I've seen is that for some reason valid coefficients are getting caught on the clause that I've marked with a "#" and the reference to the head of my list (the Term first variable) doesn't seem to be getting additional variables from the inputted string linked to it properly. Any help you can give would be much appreciated, thanks in advance. There are many required methods but this the relevant code for the problem I'm experiencing:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Polynomial
{
// instance variables
private Term first;
private int numTerms;
/**
* Constructor for objects of class Polynomial
*/
public Polynomial(String s)
{
Pattern whiteSpace = Pattern.compile(" ");
String[] poly = whiteSpace.split(s);
double coefficient;
int exponent;
if(poly.length % 2 == 1) {
throw new IllegalArgumentException();
}
first = new Term(); // dummy variable so that checking the first term specially is unnecessary
for(int term = 0; term < poly.length; term += 2) {
if(poly[term].matches("[\\-][0-9]||[0-9]||[0-9][\\.][0-9]||[\\-][0-9][\\.][0-9]")) {
coefficient = Double.parseDouble(poly[term]);
if(poly[term + 1].matches("[0-9]")) {
exponent = Integer.parseInt(poly[term++]);
} else {
throw new IllegalArgumentException(); //#
}
numTerms++;
this.addTerm(coefficient, exponent);
}
}
}
public void addTerm(double coef, int exp)
{
if(coef == 0) {
throw new IllegalArgumentException();
}
Term pointer = first;
while(pointer.next != null) {
if(exp == pointer.next.exponent) {
if(coef + pointer.next.coefficient == 0) {
pointer.next = pointer.next.next;
numTerms--;
} else {
pointer.next.coefficient += coef;
break;
}
} else if(pointer.next.exponent < exp) {
Term newTerm = new Term(coef, exp, pointer.next.next);
pointer.next = newTerm;
numTerms++;
break;
}
pointer = pointer.next;
}
}
private class Term {
double coefficient;
int exponent;
Term next;
Term() {
next = null;
}
Term(double coef, int exp, Term nextTerm) {
coefficient = coef;
exponent = exp;
next = nextTerm;
}
}`
You do not need regex to check for validity ParseXXX() takes care of that. If parsing fails, an Exception is thrown and then you can simply throw IllegalArgumentException
for (int term = 0; term < poly.length - 1; term += 2) {
try {
coefficient = Double.parseDouble(poly[term]);
exponent = Integer.parseInt(poly[term + 1]);
numTerms++;
this.addTerm(coefficient, exponent);
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
}
Moreover, using regex = "[0-9]" means only a single digit exponent. You might want to change it to "[0-9]+"
I have a problem where I have to store an integer, if a user answers Y, from an input and then using it on a method, storing that integer and then adding it to a different input from the user. The total will be used on the same method and printed only if the user inputs N.
For instance,
Y
input =3
method(input)
Y
input = 4
method(input)
N
total = 3+4
method(input, total)
I have most of the code already, I just want to know if it is possible to get the total and use it on the method
Edit: here is the code
public static boolean walk(boolean bool, String answer) {
while(bool==true) {
if (answer.equals("Y") || answer.equals("y")) {
return bool=true;
}
else if (answer.equals("N") || answer.equals("n")) {
return bool=true;
}
}
return bool;
}
public static boolean continueWalking(boolean bool, String answer, int average) {
while(bool==true){
if (answer.equals("Y") || answer.equals("y")){
return bool=true;
}
else if(answer.equals("N") || answer.equals("n")){
System.out.println("Great exercise!");
System.out.println(average);
System.exit(0);
}
}
return bool;
}
while(bool) {
System.out.println("Do you want to start/continue walking?");
String continueWalk=input.next();
int totsteps=numberOfSteps;
continueWalking(true, continueWalk,totsteps);
System.out.println("How many steps do you want to walk in this section?");
totsteps=numberOfSteps + numberOfSteps;
int numberOfSteps = input.nextInt();
NumOfsteps(numberOfSteps,1);
}
Just a couple of syntax/formatting things to start with:
your while statement while(bool==true) can be changed to just while(bool). A while loop statement just needs to evaluate to a boolean in Java, and boolean bool is already a boolean. You can do a similar thing for your return statements, change them to return bool;
To answer your question, to update an int value in Java, use +=.
int test = 0;
test += 1;
System.out.println(test); // Prints out 1
In your code, declare totsteps outside of the while loop, and change the line int totsteps=numberOfSteps; to totsteps += numberOfSteps;
Having a String representation of a number(no decimals), what's the best way to convert it to either one of java.lang.Integer or java.lang.Long or java.math.BigInteger? The only condition is that the converted type should be of minimal datatype required to hold the number.
I've this current implementation that works fine, but I would like to know if there's a better code without exception handling.
package com.stackoverflow.programmer;
import java.math.BigInteger;
public class Test {
public static void main(String[] args) {
String number = "-12121111111111111";
Number numberObject = null;
try {
numberObject = Integer.valueOf(number);
} catch (NumberFormatException nfe) {
System.out.println("Number will not fit into Integer type. Trying Long...");
try {
numberObject = Long.valueOf(number);
} catch (NumberFormatException nfeb) {
System.out.println("Number will not fit into Long type. Trying BigInteger...");
numberObject = new BigInteger(number);
}
}
System.out.println(numberObject.getClass() + " : "
+ numberObject.toString());
}
}
From what you said, here is what I would have done:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
public class TestSO09_39463168_StringToMinimalNumber {
public static void main(String[] args) {
List<String> strNumbers = Arrays.asList("0", //int
"123", //int
"-456", //int
"2147483700", // Long
"-2147483700", // Long
"9223372036854775900", //BigInt
"-9223372036854775900" //BigInt
);
for(String strNumber : strNumbers){
Number number = stringToMinimalNumber(strNumber);
System.out.println("The string '"+strNumber+"' is a "+number.getClass());
}
}
public static Number stringToMinimalNumber(String s){
BigInteger tempNumber = new BigInteger(s);
if(tempNumber.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0){
return tempNumber;
} else if(tempNumber.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0){
return tempNumber.longValue(); //Autobox to Long
} else {
return tempNumber.intValue(); //Autobox to Integer
}
}
}
You must use a temporary BigInteger, or else you'll end up with lazarov's solution, which is correct, but you can't really do something like that for reason mentionned in the comments.
Anyway, every BigInteger (the ones that are not returned) will be garbage collected. As for autoboxing, I don't think it's that of a bad thing. You could also make "BigInteger.valueOf(Long.MAX_VALUE))" as a constant. Maybe the compiler or the JVM will do this on its own.
I'm not really sure of how efficient it is, and using only BigInteger might be a good idea (as Spotted did), because I serioulsy doubt it would really improve the rest of your code to use the right size, and it might even be error prone if you try to use these Numbers with each other ... But again, it all depend on what you need. (and yes, using Exception as flow control is a really bad idea, but you can add a try catch on the BigInteger tempNumber = new BigInteger(s); to throw your own exception if s is not a number at all)
For recreational purpose, I have made the solution without using a BigInteger, and only with String parsing (this is still not what I recommand to do, but it was fun :)
public static final String INT_MAX_VALUE = "2147483647";
public static final String LONG_MAX_VALUE = "9223372036854775807";
public static Number stringToMinimalNumberWithoutBigInteger(String numberStr){
//Removing the minus sign to test the value
String s = (numberStr.startsWith("-") ? numberStr.substring(1,numberStr.length()) : numberStr);
if(compareStringNumber(s, LONG_MAX_VALUE) > 0){
return new BigInteger(numberStr);
} else if(compareStringNumber(s, INT_MAX_VALUE) > 0){
return new Long(numberStr);
} else {
return new Integer(numberStr);
}
}
//return postive if a > b, negative if a < b, 0 if equals;
private static int compareStringNumber(String a, String b){
if(a.length() != b.length()){
return a.length() - b.length();
}
for(int i = 0; i < a.length(); i++){
if( a.codePointAt(i) != b.codePointAt(i) ){ //Or charAt()
return a.codePointAt(i) - b.codePointAt(i);
}
}
return 0;
}
Please don't use exceptions for handling flow control, this is a serious anti-pattern (also here).
As you mentionned in the comments, the real thing you've been asked is to convert a List<String> into a List<Number>.
Also, if I understand correctly, you know that:
You should encounter only numbers without decimals
The biggest value you can encounter is possibly unbound
Based on that, the following method will do the job in a more clever way:
private static List<Number> toNumbers(List<String> strings) {
return strings.stream()
.map(BigInteger::new)
.collect(Collectors.toList());
}
Eidt: if you're not very familiar with the stream concept, here's the equivalent code without streams:
private static List<Number> toNumbers(List<String> strings) {
List<Number> numbers = new ArrayList<>();
for (String s : strings) {
numbers.add(new BigInteger(s));
}
return numbers;
}
Well if you want to do it "by hand" try something like this:
We define the max values as strings :
String intMax = "2147483647";
String longMax = "9223372036854775807";
and our number:
String ourNumber = "1234567890"
Now our logic will be simple :
We will check lenghts of strings firstly
If our numbers length < int max length : IT IS INT
If our numbers length == int max length : Check is it INT or LONG
If our numbers length > int max length :
3.1 If our numbers length < long max length : IT IS LONG
3.2 If our numbers length == long max length : Check is it LONG or BIG INTEGER
3.3 If our numbers length > long max length : IT IS BIG INTEGER
The code should look something like this (I have not tried to compile it may have syntax or other errors) :
if(ourNumber.lenght() < intMax.length ){
System.out.println("It is an Integer");
} else if(ourNumber.lenght() == intMax.length){
// it can be int if the number is between 2000000000 and 2147483647
char[] ourNumberToCharArray = ourNumber.toCharArray();
char[] intMaxToCharArray = intMax.toCharArray();
int diff = 0;
for(int i = 0; i < ourNumberToCharArray.length; i++) {
diff = Character.getNumericValue(intMaxToCharArray[i]) - Character.getNumericValue(ourNumberToCharArray[i]);
if(diff > 0) {
System.out.println("It is a Long");
break;
} else if(diff < 0) {
System.out.println("It is an Integer");
break;
}
}
if(diff == 0){
System.out.println("It is an Integer");
}
} else {
if(ourNumber.lenght() < longMax.length()) {
System.out.println("It is a Long");
} else if(ourNumber.lenght() == longMax.length()){
char[] ourNumberToCharArray = ourNumber.toCharArray();
char[] longMaxToCharArray = longMax.toCharArray();
int diff = 0;
for(int i = 0; i < ourNumberToCharArray.length; i++) {
diff = Character.getNumericValue(longMaxToCharArray[i]) - Character.getNumericValue(ourNumberToCharArray[i]);
if(diff > 0) {
System.out.println("It is a BigInteger");
break;
} else if(diff < 0) {
System.out.println("It is a Long");
break;
}
}
if(diff == 0){
System.out.println("It is a Long");
}
} else {
System.out.println("It is a BigInteger");
}
}
Then logic that checks if the numbers match or not is the same in both cases you can but it in a function for example.
I have a desktop application with textboxs that contain a price values. As an example if i input 25000
Double priceSec = Double.parseDouble(cusPrice.getText());
i'm passing that 25000 as a double value
so now i want to compare that value and check whether it is empty or not?
if(cusPrice2.getText()==null || cusPrice2.getText().isEmpty()){
Double priceSec=0.0;
}
i know i can create an else condition for
if textbox !=null
total=txtbox1+txtbox2+txtbox3;
if textbox value is empty or not empty. value should be there in total.
but in my code ,it displays as null.
Do i have any other way to do that?
can you tell me a way to do that.
here is my full code
private void cusOkBtnActionPerformed(java.awt.event.ActionEvent evt) {
Double priceSec = Double.parseDouble(cusPrice2.getText());
Double priceThird = Double.parseDouble(cusPrice3.getText());
Double priceFourth = Double.parseDouble(cusPrice4.getText());
Double priceFifth = Double.parseDouble(cusPrice5.getText());
if(cusPrice2.getText()==null || cusPrice2.getText().isEmpty() || cusPrice2.getText() !=null ){
priceSec=0.0;
costCls.setItemPrice(priceSec);
}
else if(cusPrice3.getText()==null || cusPrice3.getText().isEmpty()){
priceThird=0.0;
}
else if(cusPrice4.getText()==null || cusPrice4.getText().isEmpty()){
priceFourth=0.0;
}
else if(cusPrice5.getText()==null || cusPrice5.getText().isEmpty()){
priceFifth=0.0;
}
Double setItemTotal = priceCus+priceSec+priceThird+priceFourth+priceFifth;
}
You should rather use Exceptions.
try {
Double priceSec = Double.parseDouble(cusPrice.getText());
} catch (NullPointerException e1) {
//null somewhere
} catch (NumberFormatException e2) {
//not a number - on controlled input - empty field.
}
double is the primitive type for floating point, Double is the Object child that wraps a double value. So:
double priceSec = Double.parseDouble(cusPrice.getText());
double price2Sec = cusPrice2.getText().isEmpty())
? 0.0
: Double.parseDouble(cusPrice.getText());
if (priceSec == price2Sec) { ...
However for financial data a double has small approximation errors, that can become visible - especially with ==. Hence one might better use BigDecimal, which does fixed point arithmetic.
BigDecimal priceSec = new BigDecimal(cusPrice.getText());
if (priceSec.compareTo(price2Sec) == 0) { ...
With a bit ugly API doing calculations:
x = x.add(y.divide(new BigDecimal("12.50")));
you can try this
private void cusOkBtnActionPerformed(java.awt.event.ActionEvent evt) {
Double priceSec=0.0,priceThird=0.0,priceFourth=0.0,priceFifth=0.0;
costCls.setItemPrice(0.0);
if(cusPrice2.getText()!=null && !cusPrice2.getText().isEmpty() ){
priceSec = Double.parseDouble(cusPrice2.getText());
costCls.setItemPrice(priceSec);
}
else if(cusPrice3.getText()!=null && !cusPrice3.getText().isEmpty()){
priceThird = Double.parseDouble(cusPrice3.getText());
}
else if(cusPrice4.getText()!=null && !cusPrice4.getText().isEmpty()){
priceFourth = Double.parseDouble(cusPrice4.getText());
}
else if(cusPrice5.getText()!=null && !cusPrice5.getText().isEmpty()){
priceFifth = Double.parseDouble(cusPrice5.getText());
}
Double setItemTotal = priceCus+priceSec+priceThird+priceFourth+priceFifth;
}
It is better to use the built-in Exception semantics already available within the Double.parseDouble(String s) implementation. (IMHO: Don't check up-front as you are making the exceptional-situation part of the normal flow)
Use a function like
private static double getValue(String str) {
try {
return Double.parseDouble(str);
} catch (NumberFormatException e) {
return 0d;
}
}
You would then use it like:
String priceStr = cusPrice.getText();
double d = getValue(priceStr);