为什么这种方法仍然会对货币产生舍入错误?

时间:2014-06-02 00:26:47

标签: c math floating-point rounding-error

这是代码:

float accountBalance = 0; //global

//this function gets called many times  
int Accumulate(float amount) //amount in currency form, i.e. xxx.yy
{
   float fixroundVal = 0;

   amount = amount * 100; //change to full number (removes decimals)

   accountBalance += amount;

   fixroundVal = accountBalance / 100;

   printf("fixroundVal=%f",fixroundVal);//really gets stored   

}

所以之前,我没有使用fixroundVal值并缩放100 - 它只是accountBalance += amount;

我的舍入错误非常糟糕,所以我每次迭代都进行了100次本地缩放,它摆脱了很多舍入错误但是偶尔,我还是会得到一些

我尝试将100比例增加到10的其他倍数,实际上我得到了更多的舍入错误。

我只能使用C,没有库。

我该如何解决这个问题?

(更尊重银行软件;)

3 个答案:

答案 0 :(得分:7)

这是因为当您将结果除以100时,您仍然在进行浮点除法并将结果存储在浮点表示中。浮点数只能通过使用二进制的分数来近似。你必须得出1/2 1/4 1/8等与实际实际值的最接近的总和。例如0.2的某些数字不能精确地以浮点表示。

解决方案是将美元金额表示为整个系统中整数的分数。那么你可以完全代表20美分。

答案 1 :(得分:2)

潜在的问题是使用float,它是一个二进制浮点数(通常)。

0.01的许多倍数无法在二进制浮点中精确表示 float之类的数字,例如0.10。所以当你写0.10并将其分配给float时, 得到的与0.1的值不完全相同,但是值略大于0.1。 添加两个float也不能解决问题,因为确切的值 添加浮点数,而不是它们的近似值。例如,0.1作为浮点数,加上0.1作为另一个浮点数 float,会导致数字略大于0.2,而不是0.2。

答案 2 :(得分:0)

given that you want to round up if fraction is >= .05 and otherwise, round down

int Accumulate(float amount) //amount in currency form, i.e. xxx.yy
{
    float fValue = (amount * 100.0) + .5;

    int   iValue = floor(amount); // rounds down to nearest decimal value

    printf("fValue=%f",fValue);//really gets stored   

    return( iValue ); // return rounded value (*100) to caller
}