Странные выходы 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. Он делает именно те вычисления, которые вы ожидаете быть точными для коротких десятичных дробей. Для неточных расчетов предлагает хороший выбор методов округления.
По сути, он выполняет целочисленную арифметику с масштабным коэффициентом, но автоматизирует хранение и управление масштабом.