2014-12-22 2 views
2

Ладно, так что я сделал некоторые испытания на моей программе здесь:мусора возвращенное значение Sum C++

#include <iostream> 
#include <cstring> 
#include <windows.h> 
using namespace std; 

void calcTwinkieChange(); 

int main(){ 
     calcTwinkieChange(); 
     return 0; 
} 

void calcTwinkieChange(){ 
    const double tCost(3.50); 
    const char DL1[3] = "DL", DL2[3] = "Dl", DL3[3] = "dl", DL4[3] = "dL"; 
    const char QR1[3] = "QR", QR2[3] = "Qr", QR3[3] = "qr", QR4[3] = "qR"; 
    const char DM1[3] = "DM", DM2[3] = "Dm", DM3[3] = "dm", DM4[3] = "dM"; 
    const char NK1[3] = "NK", NK2[3] = "Nk", NK3[3] = "nk", NK4[3] = "nK"; 
    double totalMoney(0), totalChange(0); 
    char inTyp[3]; 
    while(totalMoney < tCost){ 
     system("CLS"); 
     cout << "Input \"DL\" for dollar, \"QR\" for quarter, \"DM\" for dimes, and \"NK\" for nickels:" << endl; 
     cin >> inTyp; 

     if(strncmp(inTyp, DL1, 3) == 0 || strncmp(inTyp, DL2, 3) == 0 || strncmp(inTyp, DL3, 3) == 0 || strncmp(inTyp, DL4, 3) == 0){ 
     totalMoney += 1.00; 
     cout << "Amount: $" << totalMoney << endl; 
     system("PAUSE"); 
     } 
     else if(strncmp(inTyp, QR1, 3) == 0 || strncmp(inTyp, QR2, 3) == 0 || strncmp(inTyp, QR3, 3) == 0 || strncmp(inTyp, QR4, 3) == 0){ 
     totalMoney += 0.25; 
     cout << "Amount: $" << totalMoney << endl; 
     system("PAUSE"); 
     } 
     else if(strncmp(inTyp, DM1, 3) == 0 || strncmp(inTyp, DM2, 3) == 0 || strncmp(inTyp, DM3, 3) == 0 || strncmp(inTyp, DM4, 3) == 0){ 
     totalMoney += 0.10; 
     cout << "Amount: $" << totalMoney << endl; 
     system("PAUSE"); 
     } 
     else if(strncmp(inTyp, NK1, 3) == 0 || strncmp(inTyp, NK2, 3) == 0 || strncmp(inTyp, NK3, 3) == 0 || strncmp(inTyp, NK4, 3) == 0){ 
     totalMoney += 0.05; 
     cout << "Amount: $" << totalMoney << endl; 
     system("PAUSE"); 
     } 
     else{ 
      Beep(1000, 300); 
       cout << "Invalid Input, Please Try Again..." << endl; 
       system("PAUSE"); 
     } 
    } 
    /* 
    cout << "Total Cost: " << tCost << " " << totalMoney << " " << totalChange << " "; 
    system("PAUSE"); 
    */ 
//--- I believe the issue resides on the line bellow. It may contain an uninitialized variable— somehow. --- 
    totalChange = (totalMoney - tCost); 
    cout << "Enjoy your deep fried Twinkie..." << endl; 
    cout << "Your change: $" << totalChange << endl; 
    system("PAUSE"); 
} 

Программа предназначена брать доллары, кварталы, пятаков и никелевые один за другим, пока сумма Достигнуто $ 3,50, в котором программа вернется «Наслаждайтесь своим жареным Twinkie». а также вернуть надлежащее количество изменений, если это применимо.

Программа отлично работает и возвращается изменить должным образом, пока я не вошел в 35 пятаков и получил это как мой ответ на изменения:

enter image description here Я также считаю, это то же самое произошло, когда ввод 70 никелевые, и возвращается значение мусора.

Любое понимание источника моей проблемы очень ценится. Следует также упомянуть, что мой учитель C++ не получил этот эфир, поэтому я здесь.

+2

Вы должны прочитать [Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). Я действительно понимаю, что большинство компьютерных ученых ** не знают об этом. Даже если бы они знали об этом в какой-то момент, они с тех пор об этом забыли. Тем не менее, это все еще актуально. –

+3

Высшие Существа говорили со мной. Вы получите много понимания, используя магический инструмент, называемый * отладчиком *. –

+3

Нейдерталь воспевает обратно. Говорят, что вместо этого используйте * print *; им нравятся их старые способы. –

ответ

3

«e-015» - это ваша подсказка, что «изменение» по существу равно $ 0, и что это всего лишь ошибка округления. Ваш учитель, по крайней мере, должен узнать об ошибках округления! Если у вас есть $ 0,50 или $ 0,25, это может быть представлено точно в двоичном формате, но $ 0,05 будет повторяющейся дробью в двоичном выражении и не может быть представлено точно ... бесконечная повторяющаяся последовательность 00101 будет отрубаться после 48 бит или что-то еще является. Таким образом, никель никогда не будет составлять ровно $ 3,50.

Решение заключается в том, чтобы печатать ответ только на разумное количество знаков после запятой, ИЛИ представлять все в центах вместо долларов.

Кстати, я думаю, что большинство программистов предпочли бы этот синтаксис:

сопза двойной tCost = 3,50;

вместо:

Const двойного tCost (3.50);

+0

Или 'const double tCost {3.50};' –

2

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

Проблема в том, что компьютеры не работают в десятичной форме, как люди, они работают в двоичном формате. Простой десятичный знак, такой как 0.10, не может быть представлен точно в двоичном формате, но будет немного выключен (0.10000000149011612). Поскольку вы работаете со многими такими числами, разница будет увеличена.

Смежные вопросы