试图回合数字时如何避免丧失精度?(C )

how to avoid the loss of precision when trying to round number? (C++)

本文关键字:精度 丧失 何避免 数字      更新时间:2023-10-16

刚完成了我的C 的第一周(使用Visual Studio 2017),我写了一个程序,向用户询问资金量,并将打印账单和硬币的数量。它在开始时起作用,但有时只是打印错误的数字。(当用户输入$ 1.28时,它显示1美元,1季度和2便士。)这是我的代码,有什么错吗?算法或数据类型?

#include<iostream>
using namespace std;
float Q = 0.25;
float D = 0.10;
float N = 0.05;
float P = 0.01;
float Dollar = 1;
float money;
float dollars, quarters, dimes, nickels, pennies;

int main()  //to break money into coins.
{
cout << "how many money do u have?" << endl;
cin >> money;
dollars = (int)money;
quarters = (int)((money - dollars*Dollar)/Q);
dimes = (int)((money - dollars*Dollar - quarters*Q) / D);
nickels = (int)((money - dollars*Dollar - quarters*Q - dimes*D) / N);
pennies = (int)((money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) / P);
cout << "$" << money << " can be break into :" << endl;
cout << dollars << " dollars. " << endl;
cout << quarters << " quarters. " << endl;
cout << dimes << " dimes. " << endl;
cout << nickels << " nickels. " << endl;
cout << pennies << " pennies. " << endl;
}

试图回合数字时如何避免丧失精度?(C )

当您从浮点转换为整数时,分数部分会截断。为了确保整数精度损失(获取正确的"整体"),每次将结果添加为0.5,例如:

quarters = static_cast<int>(((money - dollars*Dollar)/Q)+0.5);

但是,当结果为负面时,这无效,例如:50.5-100 = -49.5-> 1 = -48.5-> -48 ...不是49

对于负面因素,您需要减去0.5。

我想,在行中

pennies = (int)((money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) / P);

零件(money - dollars*Dollar - quarters*Q - dimes*D - nickels*N)将产生一个值,而不是完全.03,而是下面的一个值。这是由于浮点算术的性质,您应该对此进行阅读。鉴于它是.029999999995之类的,因此除以0.01不会产生3.0,但也许不会产生2.9999999995。由于您没有四舍五入,而是将价值投放到整数,因此该期间后的整个部分将被扔掉,因此会导致2便士。

您如何解决此问题?

最简单的是要绕过值而不是施放值,这应该产生正确的价值,但这是对问题的刺激性解决方案。您也可以尝试使用double而不是float,但这也无法解决问题。您可能会得到正确的,但是相同的仍然可能发生类似的错误。

存储整个便士

您可以将全部数量存储为整数(整个便士)

int amountInPennies;
int penniesPerDollar = 100;
int penniesPerQuarter = 25;
int penniesPerDime = 10;
int penniesPerNickle = 5;
int totalDollars = amountPennies / penniesPerDollar;
int totalQuarters = (amountPennies - totalDollars * penniesPerDollar) / penniesPerQuarter;
...

小数类型

在处理金钱的现实世界应用中(嗯,取决于类型),您很可能会使用某种小数类型而不是float。根据此答案,有gnu许可下的算术算术的库。您仍然可以滚动自己的十进制类型,即或多或少地做我在第一种方法中所介绍的事情。这可能是一个很好的学习,但是当涉及现实世界应用时,现成的库可能是更好的选择。