0

I am a newbie with Java and I'm making a very simple Java program like this:

package exercise7; 
import java.util.Scanner;

public class Exercise7 {

    public static void main(String[] args) {
        // TODO code application logic here
        Scanner keyboard = new Scanner(System.in);

        System.out.println("Enter a number between 0.0 and 1.0.");
        keyboard.nextDouble();
    }
}

My problem is, when I enter 0.1 for example, they said to me that I had this problem:

Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextDouble(Scanner.java:2413)
at exercise7.Exercise7.main(Exercise7.java:30)C:\Users\Anh Bui\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1BUILD FAILED (total time: 7 seconds)

I am very confusing, because I thought that nextDouble could mean 0.1 or something like that? Could you please help me? Thank you very much.

anhbuiask
  • 63
  • 1
  • 2
  • 8
  • Your code is working fine for me, when I type `0.1` – racraman Feb 01 '20 at 05:05
  • 1
    Maybe "they" didn't follow the rules set forth by the prompt - silly users - such as entering the letter 'a' at the prompt produces the exception. –  Feb 01 '20 at 05:11
  • @Andy hah, "sillly users", "with all of this tries we still can't get them of providing wrong data, errors, incombatible formats, etc., oh those users, the implicit requirement of telling this to all of them is crushing, destroing the spririt..." – itwasntme Feb 01 '20 at 05:14

1 Answers1

3

The reason between this is just between using 1.1 or 1,1 in different zones.

The way the Scanner reads the nextDouble is related to your Locale or Zone setting (which, if not overrided, are loaded from system).

For example, I'm in Poland and my delimiter for decimal or floating point numbers is , and regardless the Java standard syntax is to use dot(.), if I input some number with . I'll also get InputMismatchException, but when I use ,, e.g. 0,6 it finishes flawlessly.

In the same time, regardless of the Zone or Locale, the valueOf or parseDouble methods from Double class are using . as floating point separator.

Scanner class methods starting with next... are based on the built-in patterns for discovering the proper values. The discovery pattern is build with the common/regular way of writing numbers/values (of the specified type) in your country/zone.

This is very similar to the Data types, which differs even more on their zone of use.

One of the ways of handling InputMismatchException here is to catch this exception and require the user to provide the number again, similarly to this question.
Your case is a bit different from the input of natural number (because 1.1 and 1,1 should indicate the floating point number.
The simplest way of handling those two separators for decimal numbers would be to read the input as String, replace the wrong separator and parse to double, like:

static double getDouble(String doubleS) {
    doubleS = doubleS.replace(',', '.');
    try {
        return Double.parseDouble(doubleS);
    } catch (NumberFormatException e) {
        e.printStackTrace();
        throw e;
    }
}

Thanks to @Andreas comment, the most appropiate way of handling this would to require the user to provide a decimal number with . separator, because the printed message (before input) has the separator in its numbers.
This could be done with setting the type of Scanner object locale before number input like:

Scanner keyboard = new Scanner(System.in);
keyboard.useLocale(Locale.US); //this sets the locale which has below separator
System.out.println("Enter a number between 0.0 and 1.0.");
itwasntme
  • 1,442
  • 4
  • 21
  • 28
  • 2
    To force use of `.` as decimal separator, call [`keyboard.useLocale(Locale.US)`](https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#useLocale-java.util.Locale-), or chain it after the constructor: `Scanner keyboard = new Scanner(System.in).useLocale(Locale.US);` – Andreas Feb 01 '20 at 05:37
  • @Andreas the `to force use of...` any of delimiter isn't the reason of question. But I understand the concerns. But there are lots of ways to cover possible use cases. OP stated that he thought of `0.1` as double, but resulted as `IME` in his case so obviously was because of using a wrong delimiter related to his Locale. Regardless, give me some points then I'll improve my answer (e.g. expected, enforced delimiter or others). I'll definitely try to improve it, but later, really, later (i've also starred it to keep it in my loop), but later, thanks. – itwasntme Feb 01 '20 at 06:04
  • @itwasntme thank you for your comment, I am using Japanese timezone and I thought that was the problem, when I use `0,2` for example, it was ok. – anhbuiask Feb 01 '20 at 06:18
  • @anhbuiask I believe my answer told you more than my comment, but whatever as long as it helps you. – itwasntme Feb 01 '20 at 06:22
  • I already up-voted answer, since it is the right answer. --- My comment was intended to be an *extension* of the answer, not a critique, i.e. to show that instead of expecting user to enter `1,1`, change the code to accept `1.1`, regardless of the computers locale. --- That actually seems a more appropriate solution, given that the program explicitly prints a message saying to use `.` *("Enter a number between **0.0** and **1.0**.")* --- The alternative is of course to make the prompt text show the locale-dependent decimal point. – Andreas Feb 01 '20 at 06:33
  • @Andreas : so, if I want to input 0.1 but no error, could you please show me some way to solve this problem ? – anhbuiask Feb 01 '20 at 06:43
  • 1
    @anhbuiask See [my first comment](https://stackoverflow.com/questions/60014126/java-error-exception-in-thread-main-java-util-inputmismatchexception/60014288?noredirect=1#comment106138062_60014288). – Andreas Feb 01 '20 at 06:58