分割浮点数几乎相等,没有损失

ger*_*tan 1 c c++ floating-point

假设浮点数的十进制可视化表示后的2位数(例如:货币),以最小总误差分割金额的最佳方法是什么?

例如,要将100.00平均分配给3个银行账户,我会做这样的事情:

double amount = 100.0;
double acc1 = amount / 3.0;
double acc2 = amount / 3.0;
double acc3 = amount / 3.0;
Run Code Online (Sandbox Code Playgroud)

但是,当用2位小数打印每个帐户余额时,我得到:

printf("%.2f\n", acc1);
printf("%.2f\n", acc2);
printf("%.2f\n", acc3);

33.33
33.33
33.33
Run Code Online (Sandbox Code Playgroud)

很明显,所有帐户的金额总和为99.99,由于四舍五入而损失0.01.

理想情况下,我想要一些功能/算法可以分布几乎相同和视觉打印

33.34
33.33
33.33
Run Code Online (Sandbox Code Playgroud)

这三个账户中的哪一个获得额外的0.01并不重要.

我该怎么做呢?是否有任何舍入算法名称?

tmy*_*ebu 6

你在这里犯了多个错误. double是一个双精度二进制浮点数. 100.0 / 3.0等于33.33333333333333570180911920033395290374755859375; 给予每个人的问题100.0/3.0不在于你给每个人的价格略低于蛋糕的总量,而是你试图给每个人提供比你更多的蛋糕.然后将其舍入到两个小数位,这是一个您无法合理预期保留总和的操作.

我建议在您的应用程序中使用整数美分而不是浮点数美元进行广告投放.

话虽如此,要将一块大小的蛋糕C分成浮点部分以便在n人群中分配,你可以给n-1人们一些大小C/n,最后一个人就是一块大小fma(-C/n, n-1, C).这里需要融合乘法加法,因为乘法(C/n)*(n-1)可能导致舍入误差.也可以使用fmod或完成此操作remainder.