Странные выходы Java - запуск виртуальной машины на Mac lion с Eclipse

У кого-нибудь есть идея, где моя проблема вывода?

Я написал программу на Java и запускаю ее на ВМ на Mac lion с помощью Eclipse. Вместо получения 1.41, Я получил 1.4100000000000001 на моей машине.

Example:
Enter the number of quarter: 4
Enter the number of dimes: 3
Enter the number of nickels: 2
Enter the number of pennies: 1

Total $1.4100000000000001

Example: 
Enter the number of quarter: 3
Enter the number of dimes: 2
Enter the number of nickels: 1
Enter the number of pennies: 6

Total $1.06

Example:
Enter the number of quarter: 5
Enter the number of dimes: 7
Enter the number of nickels: 4
Enter the number of pennies: 4

Total $2.1900000000000004

Иногда кажется, что результаты являются правильными, а в других случаях возникают проблемы.

Код:

import java.util.*;

public class CountChange
{
    public static void main(String[]args)
    {   
        Scanner inputScanner = new Scanner(System.in);
        System.out.print("Enter the number of quarters: ");
        int quarters = inputScanner.nextInt();
        System.out.print("Enter the number of dimes: ");
        int dimes = inputScanner.nextInt();
        System.out.print("Enter the number of nickles: ");
        int nickles = inputScanner.nextInt();
        System.out.print("Enter the number of pennies: ");
        int pennies = inputScanner.nextInt();
        inputScanner.close();

        double total =0.00;
        total = quarters * 0.25 + dimes * 0.1 + nickles * 0.05 + pennies * 0.01;

        System.out.println("Total $" + total);
        System.out.print("Thank you");
    }
}

3 ответа

Ваша проблема связана с тем, как с плавающей точкой (поставить легко, float/double соответствующие расчеты). Числа с плавающей точкой являются приблизительным представлением (если вас интересует теория позади, стандартом является IEEE754). Здесь вы получите именно это, приблизительное представление.

Поскольку вы обрабатываете деньги, которые идут только в центах (вы не можете иметь 0,0001$ в валюте), я предлагаю представлять значения с int (или же longили любой целочисленный тип) значения в виде центов. Затем разделите на 100, когда показывает результат.

Вы испытали неточность представления чисел с плавающей точкой в ​​виде double s. Число 0.1 не может быть представлено точно в двоичном виде, поэтому, когда вы говорите, 0.1 в Java вы получаете максимально возможное приближение к 0.1, То же самое относится и к 0.05 а также 0.01,

Есть несколько вещей, которые вы можете сделать:

  • Отложите арифметику с плавающей точкой как можно дольше.

Пример:

total = quarters * 25 + dimes * 10 + nickles * 5 + pennies;
total /= 100.0;
  • Использовать DecimalFormat отрезать дисплей после двух десятичных знаков.

Пример:

DecimalFormat df = new DecimalFormat("0.00");
System.out.println("Total $" + df.format(total));

Ни один из этих обходных путей не обходит основную проблему - неточное представление числа double, Специально для денег, не используйте double, Вы могли бы даже использовать BigDecimal вместо этого, чья точность является произвольной.

Я согласен с объяснениями, почему вы столкнулись с этой проблемой. Мое рекомендуемое решение для такой ситуации в Java - использовать BigDecimal. Он делает именно те вычисления, которые вы ожидаете быть точными для коротких десятичных дробей. Для неточных расчетов предлагает хороший выбор методов округления.

По сути, он выполняет целочисленную арифметику с масштабным коэффициентом, но автоматизирует хранение и управление масштабом.

Другие вопросы по тегам