mmz
mmz

Reputation: 23

Java Ternary operator outputs different result than if else statement

I'm writing a program that takes a number and removes the trailing zeros if the number is an integer. I am using the ternary operator but it doesn't work as expected. But if I write it as a if else statement it works.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double number = scanner.nextDouble();
        System.out.println(((int)number == (double)number) ? (int)number : number); // Always outputs a double

        if ((int)number == (double)number) { // Outputs correct result
            System.out.println((int)number);
        }
        else {
            System.out.println(number);
        }
    }

}

For example if I input 5 i get

5.0
5

if I input 7.3 I get

7.3
7.3

So it seems that it works for the if else statement but not the ternary operator.

Upvotes: 2

Views: 186

Answers (3)

ThatsNasu
ThatsNasu

Reputation: 31

To extend the provided info on this question: The key to understand the tables provided by the JLS 15.25 is the bnp / lub operation, which stands for "Binary Number Promotion" / "Least Upper Bound".

Binary Number Promotion is the conversion of a smaller numeric type to a larger numeric type, so that integer and floating-point operations may take place. This is so you can operate on bitlevel (comparisons, equasions, etc) on different types of numerical data. byte (8 bit) will be upgraded to char (16 bit) if neccessary and so would char to short (16 bit). After that shorts would be converted to int (32 bit) if needed to ensure compatibility when operating. The int (32 bit) values are also converted to long (64 bit) if neccessary. The long (64 bit) and float (32 bit) are converted to double (64 bit) values, as required.

So in short: with BNP the smaller data types will be converted to the bigger ones to ensure compatibility.

Least Upper Bond is doing pretty much the opposite. If you have a short (16 bit) and an int (32 bit) but the int does not store a value bigger than 16 bit, the LUB operation will shrink it down to 16 bit.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503839

In your if/else statement, you're calling PrintStream.println(int) or PrintStream.println(double) depending on which branch you're taking.

With the conditional operator ?: you're always calling PrintStream.println(double), because that's the type of the ?: expression. When the second and third operands of the ?: operator have different types, the compiler picks the overall type of the expression according to the rules of JLS 15.25 and performs appropriate conversions where necessary.

In this case, the overall type is double, so it's as if you're writing:

double tmp = ((int) number == (double)number) ? (int)number : number;
System.out.println(tmp);

Upvotes: 8

Markus Spöri
Markus Spöri

Reputation: 116

This behavior is totally fine and caused by the type resolution.

The ternary operator itself has a type, that is inferred by the possible outcomes. Since one outcome has type (int) and the other has type (double), the type of the ternary operator is always double.

The rest of the story should be clear. Printing a double to the console will always result in a decimal point representation.

Upvotes: 1

Related Questions