Мои математические выражения Java с использованием Math.floor () выходят в 0 вместо намеченного числа, хотя мои бумажные вычисления говорят, что должно быть иначе - PullRequest
1 голос
/ 05 октября 2019

Я начинающий программист и пишу программу изменения машины. У меня почти нет, но по какой-то причине Math.floor() дает результат 0 вместо намеченного числа.

Я пытался использовать Math.round() вместо этого, но я вполне уверен, что это должно быть Math.floor() для наиболее точных результатов.

    public void calculateChange(){
        changeTotal = moneyGiven -  total;

        wholeDollars = Math.floor(changeTotal);

        quarters = Math.floor((changeTotal - wholeDollars)/.25);

        dimes = Math.floor(((changeTotal - wholeDollars) - quarters * .25)/.1);

        nickles = Math.floor(((changeTotal - wholeDollars) - quarters * .25 - dimes * 0.1)/.05);

        pennies = Math.floor(((changeTotal - wholeDollars) - quarters * .25 - dimes * 0.1 - nickles * .05)/ .01);
     }

Например, когда я запускаю описанный ниже метод с вводом 5 долларов в качестве предоставленных денежных средств и 1,29 долларов в качестве общей суммы транзакции, я получаю сдачу в размере 3 долларов, 2 квартала, 2 цента, 0 никелей,и 0 копеек.

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

Ответы [ 3 ]

1 голос
/ 05 октября 2019

Я бы немного переосмыслил решение здесь. В вашем подходе нет ничего плохого, но размышление об этом с использованием целочисленной математики, а не с плавающей запятой, упростит всю операцию. Вы также можете использовать промежуточные переменные, чтобы избежать повторения одних и тех же операций снова и снова.

int dollars = (int) (changeTotal);
int cents = (int) (changeTotal * 100) % 100;

int quarters = cents / 25;
cents = cents % 25;

int dimes = cents / 10;
cents = cents % 10;

int nickels = cents / 5;
cents = cents % 5;

int pennies = cents;
1 голос
/ 05 октября 2019

Вы, кажется, объявили свои переменные как числа с плавающей запятой и в результате получаете ошибки округления.

Я приведу ваш пример с 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.

1 голос
/ 05 октября 2019

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

Кроме того, ваши переменные должны быть преобразованы в целые числа. Я внес изменения в структуру вашего метода;moneyGiven и total теперь являются параметрами с плавающей точкой.

Вызов метода как calculateChange(5, 1.29f) дал мне правильный вывод 3 2 2 0 1.

public static void calculateChange(float moneyGiven, float total) {
    float changeTotal = moneyGiven - total;

    int wholeDollars = (int) Math.floor(changeTotal);

    int quarters = (int) Math.floor((changeTotal - wholeDollars)/.25);

    int dimes = (int) Math.floor(((changeTotal - wholeDollars) - quarters * .25)/.1);

    int nickles = (int) Math.floor(((changeTotal - wholeDollars) - quarters * .25 - dimes * 0.1)/.05);

    int pennies = (int) Math.floor(((changeTotal - wholeDollars) - quarters * .25 - dimes * 0.1 - nickles * .05)/.01);

    System.out.println(wholeDollars + " " + quarters + " " + dimes + " " + nickles + " " + pennies);
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...