Вы, кажется, объявили свои переменные как числа с плавающей запятой и в результате получаете ошибки округления.
Я приведу ваш пример с moneyGiven = 5.00
долларами и total = 1.29
долларами.
Хотя значение выражения (changeTotal - wholeDollars)
равно 0.71
, а значение quarters * .25
равно 0.5
, вычитание их в выражении g (changeTotal - wholeDollars) - quarters * .25
фактически приводит к 0.20999999999999996
из-за того, что числа с плавающей запятой имеют видпредставлены в памяти и математических операциях.
В итоге результатом всего выражения ((changeTotal - wholeDollars) - quarters * .25 - dimes * 0.1 - nickles * .05)/ .01
будет 0.9999999999999953
, которое затем переходит в 0
.
Вид операцийВы также оказываете влияние. Если я изменю ваши деления на умножения на обратное, как показано ниже, я на самом деле получу 1.0000038146972645
как результат конечного выражения, которое затем обнуляется до 1
:
public static void calculateChange(double moneyGiven, double total) {
double changeTotal = moneyGiven - total;
double wholeDollars = Math.floor(changeTotal);
double quarters = Math.floor((changeTotal - wholeDollars) * 4.0);
double dimes = Math.floor(((changeTotal - wholeDollars) - quarters / 4.0) * 10);
double nickles = Math.floor(((changeTotal - wholeDollars) - quarters / 4.0 - dimes / 10.0) * 20.0);
double pennies = Math.floor(((changeTotal - wholeDollars) - quarters / 4.0 - dimes / 10.0 - nickles / 20.0) * 100);
System.out.println(wholeDollars + " " + quarters + " " + dimes + " " + nickles + " " + pennies);
}
Даже сохраняя промежуточные результатыпоскольку целые числа не полностью устраняют проблему, потому что ваши total
и moneyGiven
все еще являются значениями с плавающей запятой. Изменяя их тип с double
на float
, вы несколько смягчаете проблему, имея меньшую точность, что может привести к более благоприятному округлению. Но это не позволяет надежно решить основную проблему.
Серьезные финансовые программы никогда не должны использовать примитивные типы данных с плавающей запятой для выполнения каких-либо вычислений из-за ошибок округления. Вместо этого они используют специальный тип, называемый BigDecimal
.