C++: процентная ставка не будет отображаться как .06, .6 и т. д.

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

После тестирования все работает нормально, если только я не ввожу свой максимальный процент как 0,06, 0,6 и т. Д. По какой-то причине он не отображает максимальный процент. Если я ввожу 0,06 в качестве минимального процента, он отображается успешно, а если я использую максимальную сумму процента выше 0,06, он будет отображать сумму 0,06. Никакая другая сумма не представляет для меня проблемы.

Может ли кто-нибудь помочь мне понять, что мне нужно изменить, чтобы исправить это?

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main()
{
    //variables & named constants
    int principal = 0;
    double minimumInterest = 0.0;
    double maximumInterest = 0.0;
    int yearBase = 1;
    int years = 0;
    double balance = 0.0;

    //inputs
    cout << "Enter the beginning principal: $";
    cin >> principal;

    cout << "Enter the minimum interest rate: ";
    cin >> minimumInterest;

    cout << "Enter the maximum interest rate: ";
    cin >> maximumInterest;

    cout << "Enter the number of years the interest will accumlate: ";
    cin >> years;

    //calculations & loop
    do
    {
                  cout << "Year " << yearBase << ":" << endl; 
                  for (double rate = minimumInterest; rate <= maximumInterest; rate += .01)
                  {
                      balance = principal * pow(1 + rate, yearBase);

                      //display rate with zero decimal places
                      cout << fixed << setprecision(0);
                      cout << "     Rate " << rate * 100 << "%: $";

                      //display balance with two decimal places
                      cout << setprecision(2) << balance << endl;
                  }

                      //update years counter
                      yearBase +=1;       
    } while (yearBase <= years);
    system("pause");
    return 0;                   
}  

person Jordan Lawler    schedule 27.10.2012    source источник


Ответы (2)


Что ж, double не представляет точно десятичные значения: это двоичное число с плавающей запятой, т. е. его внутреннее представление _(-1)знак * значимый< /em> * 2показатель степени, где знак равен 0 или 1, значащее целое число без знака и показатель степени целое число со знаком. Это относительно простой аргумент, показывающий, что вы не можете точно представить, например, 0,01 или 0,6. То есть вычисление шестидесятикратного прибавления 0,01, вероятно, не равно 0,6. На самом деле, если вы напечатаете эти значения с достаточным количеством цифр, вы можете увидеть эффект:

#include <iostream>
#include <iomanip>
#include <limits>

int main()
{
    double sum;
    double small(0.01);
    double big(0.6);

    for (int i(0); i != 60; ++i) {
        sum += small;
    }

    std::cout << std::setprecision(std::numeric_limits<double>::digits10 + 4)
              << "small=" << small << "\n"
              << "big=" << big << "\n"
              << "sum=" << sum << "\n";
} 

Запуск этой программы даст что-то вроде этого:

small=0.01000000000000000021
big=0.5999999999999999778
sum=0.6000000000000003109

Если вы хотите увидеть точные значения, используемые вычислением, вам нужно установить точность на std::numeric_limits<double>::digits. Однако выглядеть это будет не очень красиво.

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

person Dietmar Kühl    schedule 27.10.2012

Ответ о неточностях с плавающей запятой верен и является причиной того, что вы не используете числа с плавающей запятой, когда говорите о деньгах.

Быстрый хак, который позволит вам работать с небольшими изменениями, заключается в изменении:

for (double rate = minimumInterest; rate <= maximumInterest; rate += .01)

to:

for (double rate = minimumInterest; rate <= (maximumInterest+0.001); rate += .01)

И это сработает. В любом случае ваши денежные расчеты в какой-то момент будут ошибочными.

Правильная реализация будет использовать арифметику с фиксированной точкой.

person aaronps    schedule 27.10.2012