cbass0
cbass0

Reputation: 21

Why do I keep getting NaN as my output?

I have created a loan payment calculator. Whenever I type in any input the output shows up as NaN. Any ideas to what I could change. The first section of code is the main method. The second is another class.

MAIN METHOD

import java.util.Scanner;

public class Assignment8 {

    public static void main(String[] args) {

        Scanner kbd = new Scanner(System.in);

        System.out.print("Enter the amount borrowed: ");
        double amountBorrowed = kbd.nextDouble();

        System.out.print("Enter the interest rate: ");
        int intRate = kbd.nextInt();

        System.out.print("Enter the minimum length of loan: ");
        int minLength = kbd.nextInt();

        System.out.print("Enter the maximum length of loan: ");
        int loanLength = kbd.nextInt();
        while (loanLength < minLength) {
            System.out.println("Invalid input: Input must be greater than minimum length of loan");
            System.out.println("Enter the maximum length of loan: ");
            loanLength = kbd.nextInt();
        }

        for (int i = minLength; i <= loanLength; i++) {
            double payment = LoanCalc.monthlyPayment(amountBorrowed,loanLength, intRate);
            System.out.println(payment);
        }

    }

}

CLASS

public class LoanCalc {
    public static double monthlyPayment(double amountBorrowed, int loanLength, int intRate) {

        double interestRate;
        double monthlyPayment;

        interestRate = intRate / 100 / 12;

        monthlyPayment = (interestRate * amountBorrowed) / (1- Math.pow((1 + interestRate) , - loanLength * 12 ));

        return monthlyPayment;
    }

}

Upvotes: 0

Views: 4585

Answers (3)

user2864740
user2864740

Reputation: 61975

My first hunch would be NaN is being introduced in Math.pow as has a huge list of conditions that will make it return NaN - see what the actual input values are.

And, now about the actual values - the interestRate will be wrong (and likely 0) because integer division is being done. Try:

 interestRate = (double)intRate / 100 / 12;

Upvotes: 2

Makoto
Makoto

Reputation: 106508

The expression interestRate = intRate / 100 / 12 is performing integer division. None of those dividends/divisors are converted to a decimal value, so you get 0.

That makes this expression interesting:

 Math.pow((1 + interestRate) , - loanLength * 12 )

The result of that is 1 (since 1 to any power is always 1). You subtract 1 from that to get 0.

Now, something interesting happens when you divide by zero in an IEEE 754 floating point value - you get NaN.

The result of a floating-point division is determined by the rules of IEEE 754 arithmetic:

  • If either operand is NaN, the result is NaN.

  • If the result is not NaN, the sign of the result is positive if both operands have the same sign, and negative if the operands have different signs.

  • Division of an infinity by an infinity results in NaN.

  • Division of an infinity by a finite value results in a signed infinity. The sign is determined by the rule stated above.

  • Division of a finite value by an infinity results in a signed zero. The sign is determined by the rule stated above.

  • Division of a zero by a zero results in NaN; division of zero by any other finite value results in a signed zero. The sign is determined by the rule stated above.

What you should be doing is casting intRate to a double instead.

interestRate = (double)intRate / 100 / 12;

Upvotes: 1

Dawood ibn Kareem
Dawood ibn Kareem

Reputation: 79875

You're dividing by zero when you work out monthlyPayment.

Because you do an integer division when you calculate interestRate, you finish up with zero. So on the next line, you're actually doing Math.pow(1, -loanLength * 12) which will always give you 1. You're subtracting the result from 1 and dividing by it. Hence division by zero.

You need that intRate parameter to be a double, not an int, so that you don't get integer division when you calculate interestRate.

You COULD do this with a cast (as per the other two answers that are currently here), but I think you'd be better off having it as a double from the beginning - when you first declare intRate in main, when you fetch it from the scanner, and also when you pass it to monthlyPayment.

Upvotes: 1

Related Questions