Random.nextDouble数学出错

时间:2014-04-28 17:01:31

标签: java random double floating-point-precision

我正在开发一个小型应用程序来存入和提取银行账户的资金。该程序运行得很好,但我得到一些具有大量尾随小数的事务的奇怪输出。我随机生成只有2位小数的双打,所以我不确定它们来自哪里。

C:\Users\Jon\Documents\Class\Java>java SavingsAccountTest
Balance: 62.0
Deposit Count: 0
Withdraw Count: 0
Annual Interest Rate: 0.09
Service Charges: 0.0
Active: false

        Withdraw first, then deposit using
        randomly generated amounts.

Balance: 62.0
Withrdaw:               Deposit:
8.76                    35.43

Your account is inactive due to: Insufficient Funds
***Unable to complete withdrawal.***

Balance: 97.43
Withrdaw:               Deposit:

16.83                   3.98


Balance: 84.58000000000001
Withrdaw:               Deposit:
99.44                   35.2

Your account is inactive due to: Insufficient Funds
***Unable to complete withdrawal.***

Press enter to continue.


C:\Users\Jon\Documents\Class\Java>

问题在于第二笔交易,开始第三组交易,余额为84.58000000000001。

这是我的主要课程的代码。

import java.util.Random;
import java.util.Scanner;

public class SavingsAccountTest
{
    public static void main(String[] args)
    {
        Random rand = new Random();

        double[] depositArray = {(double)rand.nextInt(10001)/100, 
                                         (double)rand.nextInt(10001)/100,
                                         (double)rand.nextInt(10001)/100};

        double[] withdrawArray = {(double)rand.nextInt(10001)/100, 
                                          (double)rand.nextInt(10001)/100,
                                          (double)rand.nextInt(10001)/100};

        SavingsAccount account = new SavingsAccount((double)rand.nextInt(101), 
                                                (double)(rand.nextInt(10)+1)/100.0);

        System.out.print(account.toString());

        System.out.println("\n\n\tWithdraw first, then deposit using\n\trandomly generated amounts.");

        for (int i = 0; i < 3; i++)
        {   
            System.out.println("\nBalance: " + account.getBalance());
            System.out.print("Withrdaw:\t\tDeposit:\n" +
                                    withdrawArray[i] + "\t\t\t" + depositArray[i] + "\n\n");

            account.withdraw(withdrawArray[i]);
            account.deposit(depositArray[i]);
        }

        pause();
    }

    private static void pause()
    {       
        Scanner keyboard = new Scanner(System.in);

        System.out.print("\nPress enter to continue.");
        keyboard.nextLine();
        System.out.print("\n");
    }
}

以下是SavingsAccount的存款和取款方法

public void withdraw(double amount)
{
    if (this.active && amount <= super.balance)
        super.withdraw(amount);

    else
        System.out.print("Your account is inactive due to: " + 
                                "Insufficient Funds" + "\n***Unable to complete " +
                                "withdrawal.***\n");
}       

public void deposit(double amount)
{
    if (super.balance + amount >= 25.00)
    {
        this.active = true;
        super.deposit(amount);
    }

    else
        super.deposit(amount);
}

以下是BankAccount超类的存款和取款方式:

public void withdraw(double withdraw)
{
    this.balance -= withdraw;
    withdrawCount++;
}

public void deposit(double deposit)
{
    this.balance += deposit;
    depositCount++;
}

3 个答案:

答案 0 :(得分:0)

这是因为该值以二进制形式存储。 84.58不能用二进制表示完全,但它可以接近。显然它最接近的是84.58000000000001。要解决此问题,您可以使用format or printf格式化输出..

答案 1 :(得分:0)

正如其他人所说,某些值无法用浮点表示。 This指南有很多详细信息。在对货币进行计算时,任意精度类型都更适合。 Java为此目的具有BigDecimal类型。如果您使用格式化输出的方法使用2位小数,您将在某些时候遇到计算错误。

答案 2 :(得分:0)

我建议使用整数个分数来生成随机数。 java.util.Random有一个方法nextInt(int n),可生成范围(0,n)中的数字。

你可以用整数分数来完成其余部分,只能用&#34;。&#34;格式化,或者用比例2转换为BigDecimal