javaparsingjava.util.scannerinputmismatchexception

Scanner#nextDouble fails to parse 5.2 (InputMismatchException)


Problem

I was messing around with Java today, and bumped into something that I can't fix by myself. I'm trying to get a double value from scanner but always get this error:

Exception in thread "main" java.util.InputMismatchException
    at java.base/java.util.Scanner.throwFor(Scanner.java:939)
    at java.base/java.util.Scanner.next(Scanner.java:1594)
    at java.base/java.util.Scanner.nextDouble(Scanner.java:2564)
    at Main.main(Main.java:20)

Source code:

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        final char ADD = '+';
        final char SUBTRACT = '-';
        final char MULTIPLY = '*';
        final char DIVIDE = '/';

        double num1;
        double num2;

        char operator;

        Scanner sc = new Scanner(System.in);

        num1 = sc.nextDouble();
        num2 = sc.nextDouble();
        operator = sc.next().charAt(0);

        System.out.print(num1 + " " + operator + " " + num2 + " = ");

        switch (operator) {
        case ADD:
            System.out.print(num1 + num2);
            break;
        case SUBTRACT:
            System.out.print(num1 - num2);
            break;
        case MULTIPLY:
            System.out.print(num1 * num2);
            break;
        case DIVIDE:
            System.out.print(num1 / num2);
            break;
        default:
            System.out.println("Error");
            break;
        }
    }
}

My input:

5.2

And then the exception is thrown.

I also have a small video illustrating the problem: https://streamable.com/wes4g1


Minimal example

I was even able to reproduce the issue with a very minimal setup like:

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double value = scanner.nextDouble();
        System.out.println(value);
    }
}

with the input 5.2 or any other decimal.

Inputing an actual integer value, for example just 5 works however.


Solution

  • Scanner and Locale

    It is not directly obvious from the Javadoc of Scanner#nextDouble but it is Locale-sensitive.

    There are various things that influence the way how Scanner expects numbers and text to look like that depend on your current set Locale.

    By default, Scanner uses your current systems locale (country and language settings). So you have to enter the numbers in the way they are usually written in your current region.

    Decimal separator . vs ,

    In your particular case, it is the decimal separator which you entered with . (dot) but Scanner expected a , (comma) instead. This is for example the case with a Moldovan locale, since in Moldovan comma is used instead.

    Hence, when you entered 5.2 it did not see any double, as specified by your current Locale. But when you enter 5,2, it works.

    You can read more about this in the Javadoc of Scanner, section Localized numbers. Also see this illustration from Wikipedia:

    Countries using decimal comma

    Change locale

    That said, you can use Scanner#useLocale to change the locale Scanner uses. For example:

    scanner.useLocale(Locale.ENGLISH);
    

    and then you can also work with 5.2 as input.