Missing explicit casting returns into a NaN value, why?

Hi all, I am new into Java world so please, don’t judge me :slight_smile:
I was working on second mortgage calculator and spot a the following bug into non explicit casting:

import java.text.NumberFormat;
import java.util.Scanner;

//Mortgage calculator
public class Main_backup {
public static void main(String args) {

    final byte MONTHS_IN_THE_YEAR = 12;
    final byte PERCENT = 100;

    int principal;
    int numberOfPayments;
    double monthlyInterest;

    Scanner scanner = new Scanner(System.in);

    while (true){
        System.out.print("Principal ($1K - $1M): ");
        principal = scanner.nextInt();
        if (principal >= 1000 && principal <= 1_000_000)
            break;
        System.out.println("Enter a number between 1,000 and 1,000,000.");
    }

    while (true){
        System.out.print("Annual Interest Rate: ");
        double annualInterest = scanner.nextDouble();
        if (annualInterest >= 1 && annualInterest <= 30){
            monthlyInterest = Math.pow(1 + annualInterest/PERCENT,1/(double)MONTHS_IN_THE_YEAR)-1;
            break;
        }
        System.out.println("Enter a number between 1 and 30.");
    }

    while (true){
        System.out.print("Quantidade de anos: ");
        int years = scanner.nextByte();
        if (years >= 1 && years <= 30){
            numberOfPayments = years*MONTHS_IN_THE_YEAR;
            break;
        }
        System.out.println("Enter a number between 1 and 30.");


    }
    // Formula :: M = P * r (1 + r) ^ n / ((1 + r) ^ n -1 )
    double mortgage =
            principal *
                    monthlyInterest *
                    Math.pow(1 + monthlyInterest, numberOfPayments) /
                    (Math.pow(1 + monthlyInterest, numberOfPayments) - 1);


    System.out.println(NumberFormat.getCurrencyInstance().format(mortgage));

}

}

returns
Principal ($1K - $1M): 100000
Annual Interest Rate: 3,92
Quantidade de anos: 30
R$ 468,88

but
import java.text.NumberFormat;
import java.util.Scanner;

//Mortgage calculator
public class Main_backup {
public static void main(String args) {

    final byte MONTHS_IN_THE_YEAR = 12;
    final byte PERCENT = 100;

    int principal;
    int numberOfPayments;
    double monthlyInterest;

    Scanner scanner = new Scanner(System.in);

    while (true){
        System.out.print("Principal ($1K - $1M): ");
        principal = scanner.nextInt();
        if (principal >= 1000 && principal <= 1_000_000)
            break;
        System.out.println("Enter a number between 1,000 and 1,000,000.");
    }

    while (true){
        System.out.print("Annual Interest Rate: ");
        double annualInterest = scanner.nextDouble();
        if (annualInterest >= 1 && annualInterest <= 30){
            monthlyInterest = Math.pow(1 + annualInterest/PERCENT,1/MONTHS_IN_THE_YEAR)-1;
            break;
        }
        System.out.println("Enter a number between 1 and 30.");
    }

    while (true){
        System.out.print("Quantidade de anos: ");
        int years = scanner.nextByte();
        if (years >= 1 && years <= 30){
            numberOfPayments = years*MONTHS_IN_THE_YEAR;
            break;
        }
        System.out.println("Enter a number between 1 and 30.");


    }
    // Formula :: M = P * r (1 + r) ^ n / ((1 + r) ^ n -1 )
    double mortgage =
            principal *
                    monthlyInterest *
                    Math.pow(1 + monthlyInterest, numberOfPayments) /
                    (Math.pow(1 + monthlyInterest, numberOfPayments) - 1);


    System.out.println(NumberFormat.getCurrencyInstance().format(mortgage));

}

}
returns
Principal ($1K - $1M): 100000
Annual Interest Rate: 3,92
Quantidade de anos: 30
NaN

without throuwing any error, why?

Making the question more focused since it was hard to find what cast you were talking about, this is the cast:

1/(double)MONTHS_IN_THE_YEAR

The answer is integer division. When an integer is divided by another integer, the remainder is thrown away which is called integer division. Without the cast, you have 1/12 which is going to be equal to 0. Once you cast to a double you get floating point division resulting in the value you expected. Integer division is valid in some contexts, it just happens to be wrong here. You should also get the correct result by using a double literal 1.0 instead of the integer 1:

1.0/MONTHS_IN_THE_YEAR

Thank you so much. Much more clear.

1 Like