I'm running into a bit of an issue with determining if the user input is an int or double.
Here's a sample:
public static int Square(int x)
{
return x*x;
}
public static double Square(double x)
{
return x*x;
}
I need to figure out how to determine based on the Scanner if the input is a int or double for the above methods. However since this is my first programming class, I'm not allowed to use anything that hasn't been taught - which in this case, has been the basics.
Is there anyway of possibly taking the input as a String and checking to see if there is a '.' involved and then storing that into an int or double?
Lastly, I'm not asking for you to program it out, but rather help me think of a way of getting a solution. Any help is appreciated :)
The Scanner has a bunch of methods like hasNextInt, hasNextDouble, etc. which tell you whether the "next token read by the Scanner can be interpreted as a (whatever)".
Since you mentioned you've learned about the Scanner object, I assume the methods of that class are available to you for your use. In this case, you can detect if an input is an integer, double, or just obtain an entire line. The methods you would most be interested here would be the hasNextDouble() method (returns a boolean indicating whether or not the current token in the Scanner is actually a double or not) and the nextDouble() method (if the next token in the Scanner is in fact a double, parse it from the Scanner as one). This is probably the best direction for determining input types from a file or standard input.
Another option is to use the wrapper classes static methods for converting values. These are generally named like Integer.parseInt(str) or Double.parseDouble(str) which will convert a given String object into the appropriate basic type. See the Double classes method pasrseDouble(String s) for more details. It could be used in this way:
String value = "123.45"
double convertedValue = 0.0;
try {
convertedValue = Double.parseDouble(value);
} catch (NuberFormatException nfe) {
System.err.println("Not a double");
}
This method is probably best used for values that exist within the application already and need to be verified (it would be overkill to construct a Scanner on one small String for this purpose).
Finally, yet another potential (but not very clean, straightforward, or probably correct technique) could be looking at the String object directly and trying to find if it contains a decimal point, or other indicators that it is in fact a double. You may be able to use indexOf(String substr) to determine if it appears in the String ever. I suspect this method has a lot of potential problems though (say for example, what if the String has multiple '.' characters?). I wouldn't suggest this route because it is error prone and hard to follow. It might be an option if that's what the constraints are, however.
So, IMHO, your options should go as follow:
Use the Scanner methods hasNextDouble() and nextDouble()
Use the wrapper class methods Double.parseDouble(String s)
Use String methods to try and identify the value (avoid this technique at all costs if either of the above options are available).
Since you think you won't be allowed to use the Scanner methods there are a number of alternatives you try. You mentioned checking to see if a String contains a .. To do this you could use the contains method on String.
"Some words".contains("or") // evaluates to true
The problem with this approach is that there are many Strings that contain . but aren't floating point numbers. For examples, sentences, URLs and IP addresses. However, I doubt you're lecturer is trying to catch you out with and will probably just be giving you ints and doubles.
So instead you could try casting. Casting a double to an int results in the decimal portion of the number being discarded.
double doubleValue = 2.7;
int castedDoubleValue = (int) doubleValue; // evaluates to 2
double integerValue = 3.0;
int castedIntegerValue = (int) integerValue; // evaluates to 3
Hopefully, that should be enough to get you started on writing a solution to the problem.
Can be checked like this
if(scanner.hasNextDouble()}
{
System.out.println("Is double");
}
if(scanner.hasNextDouble()}
{
System.out.println("Is double");
}
Related
I have a question regarding the behavior of the NumberFormat:
When I want to translate/parse a formatted String into a Number, then I would like to use NumberFormat, since it provides me with nice presets for thousand and decimal separators. Additionally I would like it to crash, if the provided String is not a valid Number.
An example:
// works as expected
String testInput1 = "3,1415";
NumberFormat germanNumberFormat = NumberFormat.getInstance(Locale.GERMANY);
Number number1 = germanNumberFormat.parse(testInput1);
System.out.println(number1); // prints 3.1415
// does not work as expected, cuts off the number after the 2nd decimal
// separator, expected it to crash with java.lang.NumberFormatException:
// multiple points
String testInput2 = "3,14,15";
Number number2 = germanNumberFormat.parse(testInput2);
System.out.println(number2); // prints 3.14
I currently use Double.parseDouble(String s), to have this additional behavior:
// crashes with java.lang.NumberFormatException: multiple points
double number2WithError = Double.parseDouble(testInput2.replace(",", "."));
Is there a way I can use NumberFormat to have my required/expected behavior besides writing my own wrapper class that does some additional checks on e.g. multiple decimal separators?
Also I'm aware that the JavaDoc of the used parse(String source) method of NumberFormat says:
Parses text from the beginning of the given string to produce a number. The method may not use the entire text of the given string.
See the {#link #parse(String, ParsePosition)} method for more information on number parsing.
and parse(String source, ParsePosition parsePosition):
Returns a Long if possible (e.g., within the range [Long.MIN_VALUE, Long.MAX_VALUE] and with no decimals), otherwise a Double. If IntegerOnly is set, will stop at a decimal point (or equivalent; e.g., for rational numbers "1 2/3", will stop after the 1). Does not throw an exception; if no object can be parsed, index is unchanged!
This doesn't tell me though why the method behaves this way. What I get from these is that they can parse only parts of the String (what they obviously do here) and probably just start parsing at the beginning (start position) until they find something they can't deal with.
I didn't find an existing question covering this, so if there is already one, please feel free to close this post and please link to it.
NumberFormat.parse(String) is behaving exactly as documented:
Parses text from the beginning of the given string to produce a number. The method may not use the entire text of the given string.
(Emphasis added)
You ask:
Is there a way I can use NumberFormat to have my required/expected behavior besides writing my own wrapper class that does some additional checks on e.g. multiple decimal separators?
You cannot provide a format that will make NumberFormat.parse() throw an exception for input with only an initial substring that can be parsed according to the format. You can, however, use NumberFormat.parse(String, ParsePosition) to determine whether the whole input was parsed, because the parse position argument is used not only to indicate to the method where to start, but also for the method to say where it stopped. That would be a lot better than implementing format-specific extra checks. Example:
ParsePosition position = new ParsePosition(0);
Number result = format.parse(input, position);
if (position.getIndex() != input.length()) {
throw new MyException();
}
Additionally, you write:
This doesn't tell me though why the method behaves this way.
It behaves that way because sometimes parsing the initial portion of the input is exactly what you want to do. You can build stricter parsing on top of more relaxed parsing, as shown, but it's much more difficult to do it the other way around.
I used to initialize double variables with Double.NaN and fill them later depending on the input. If there were mistakes in inputs I just return Double.NaN. This practice backfired, when other part of application used my function as input and worked just OK, doing basic arithmetic and comparing NaNs with double (but didn't supposed to, I would expect exception).
The obvious solution would be to add Double.isNaN() at the end of my code and throw exception inside my function
But this is a highly used function in highly optimized code, so I'm unwilling to add extra check each time it is called. I would rather prefer break the whole application on wrong parameters once a year than add an extra check, esp. I heard that comparing to NaN takes longer than comparing to double. How do I achieve that and what are best practices in this situation?
EDIT
for example, I want to return first parameter for parametric function which I know nothing about depending on user input
private double getFirstFactor(HashMap <String, Double> userParams) {
double res = Double.NaN;
if(userParams.containsKey("factor1")) {
res = userParams.get("factor1");
}
return res;
}
Usage
double f1 = getFirstFactor(userParams);
double threshold = f(f1); // for example f1 * 100 + f1;
// ideally, code above breaks if f1 is not defined and I don't go futher
if(threshold >= 0) {
...
} else {
...
}
Don't do that.
NaN is used for the result of certain expressions (e.g. 0.0 / 0.0) and has the unique property that it compares false with itself.
You should always initialise double values with something sensible. Depending on your algorithm, 0.0 and 1.0 are often good values.
If you really can't do that then you could always use a Double, with null as your default-initialised value.
You should always validate your inputs before using them. If your inputs are invalid, you can throw an IllegalArgumentException before any computation is done at all. It makes it the caller's responsibility to use your code with correct inputs.
It's always better to fail fast, instead propagating invalid values throughout your system. This can cause big problems (as you probably have experienced).
Use boxed type Double and use null as default value insteed of Double.NaN. If I would need to stick to primitives, I would got for 0.0d as default value.
I am trying to program (in Java) what seems like a relatively easy set of requirements but I am having trouble with types. I want to take scientific data from an instrument and put it through some logic to come up with an answer. My problem is that the data will either come off as a string (always "None") or a double. The data set will be two points per sample. So, here are my thoughts: I need class with two parameters that can be either a string or double. So, I decided I would make a class with generic parameters. When it came to performing the logic on the double or string, I had trouble. For example, here are two parts of the logic:
If v < 26 and f is between 36.5 and 37, then sample needs to be rerun.
If v > 31 and f is "None", then rerun.
There are more rules but I won't include them all here, but both v and f may be either a double or "None".
If all the values were doubles I would have no problem, but the fact that I can get doubles or strings is giving me trouble when trying to compare the two. I'm not sure if a generic class is the way to go. Any ideas?
Also, this is my first post so please let me know if you need more information or have any tips on posting.
Thanks!
You are mistaken: Your input type is always String (if it can be "None" it is a String). However, it can be a String with numbers and a dot that may be parsed as a Double.
Something like this should help:
public static Double parseInput(String input) {
try {
return input.equals("None") ? null : Double.valueOf(input);
} catch (NumberFormatException | NullPointerException e) {
return Double.NaN;
}
}
This returns a null for "None", which seems the most reasonable mapping, and handles anything not a number (blank, null, bad data) by returning the special "not a number" Double value.
I suggest you to use String as parameter type, then inside your class you can try to parse the value to double and apply your logic on it if the value can be parsed to double.
If not, then the value is a String and you have to apply the logic of String values
If all the values were doubles I would have no problem,
Similar to #Bohemian's answer but I would make use of NaN and leave the value a primitive.
public static double parseInput(String input) {
return "None".equalsIgnoreCase(input)
? Double.NaN
: Double.parseDouble(input);
}
To check for none use
If v > 31 and f is "None", then rerun.
if (v > 31 && Double.isNaN(f))
I am new to Java so forgive me if this is a silly question.
First I did the following (this is a section from my code):
public static void team()
{
int score = JOptionPane.showInputDialog("Enter the team score...");
calculate(score);
}
But I kept getting an error saying: "Incompatible types string cannot be converted to int".
So I thought I may need to use parsing. I did the following and it worked:
public static void team()
{
int myScore;
String score = JOptionPane.showInputDialog("Enter the team score...");
myScore = Integer.parseInt(score);
calculate(myScore);
}
I would like to know why there is a need for me to parse the variable "score"? In the first piece of code, I declared the variable score as an integer, so would it not store the input which I expect to be an Integer in the variable score which is then passed into the method calculate. I understand that parsing is when you convert a String into an Integer. However in this case, I do not expect the user to input a string so why is there a need for parsing?
The simple reason is: because JOptionPane.showInputDialog() returns a String, regardless of what you actually want the user to input.
There's no mechanism in Java to do automatic conversion based on the type of your destination variable myScore (though some other languages can do this, e.g. implicit conversions in Scala).
You could (in principle) create a custom dialog that returns an int , e.g. by getting the user to choose from a pulldown list of numbers, and then no parsing would be needed. But otherwise, you have to do parsing explicitly.
The JOptionPane.showInputDialog("Enter the team score..."); returns a String which you tried to store in a int. That is why you are getting the "incompatible types".
See Javadocs for more information.
Because a string is stored differently than an integer. Integers are stored in binary, while as a String is a collection of characters.
Example:
The number 14 would be stored as 1110 in Binary. However, as a String, it's stored as 00110001 00110100
Take a look at this http://www.roubaixinteractive.com/PlayGround/Binary_Conversion/The_Characters.asp
Integer.parseInt() basically does the dirty work for you, by looking up the characters in a lookup table, and as long as they correlate with proper integer values, it coverts it over to binary form, to be stored in an integer.
Edit: As always, great answer in under 5 minutes :) Turns out if I make a tiny change - make the F capital in "float", I'll get the output I expected.
class NumberMachine{
public static void main(String [] args) {
Integer wi1 = new Integer("420");
int i = 101;
Integer wi2 = i*420/101;
if(wi1 == wi2) System.out.print(" ==");
if(wi1.equals(wi2)) System.out.print(" equal");
float f = 1.23f; //if this were Float f..., it'd print Float, not double.
new NumberMachine().printIt(f);
}
void printIt(Float f){
System.out.println(" Float");
}
void printIt(double d){
System.out.println(" double");
}
}
The output is equal double, which makes no sense to me. I expected equal Float. If I comment out the 2nd printIt, then that's indeed the output. I just don't know why, when faced with a choice between the two printIt, the compiler ignored the one whose parameter matched perfectly.
You get the result you do because boxing/unboxing was added late in Java's life and it was required that pre-existing code not be changed by the addition of the feature. So when you pass in a primitive float to printIt, it gets coerced to a primitive double, because the alternative would mean old (pre-JDK1.4) code would act differently, which was an unacceptable possibility for Sun.
Basically, think if this was pre-JDK1.4 code where boxing was not an alternative, no way could the primitive double get coerced to a java.lang.Float. Adding boxing can't be allowed to break that.
Reading the question it occurs to me from how you word it you may not see the difference between Float and float, because you refer to the change from capital F to lowercase F as a tiny change, when it really isn't so tiny. The lowercase version refers to a primitive numeric type, the uppercase version refers to an object that wraps the primitive numeric type, in order to allow numeric stuff to be used in general purpose things like collections. Prior to JDK1.4 if you wanted to do something like this you had to manually write a line like
myList.add(new Float(1.0F));
if you wanted to add a float value to a list. The addition of boxing/unboxing in JDK1.4 tried to paper over this and have the compiler do this for us, but unfortunately you still have to understand the difference between the two to make sense of what's going on.