C ++中准确的百分比

时间:2014-07-19 05:22:24

标签: c++

给出2个数字,A <= B例如A = 9B = 10,我试图得到A与B相比较小的百分比。我需要有百分比作为int例如如果结果为10.00%,则int应为1000。

这是我的代码:

int A = 9;
int B = 10;

int percentage = (((1 - (double)A/B) / 0.01)) * 100;

我的代码返回999而不是1000.与double的使用相关的某些精度会丢失。

有没有办法避免在我的情况下失去精确度?

4 个答案:

答案 0 :(得分:10)

似乎您正在寻找的公式是

int result = 10000 - (A*10000+B/2)/B;

这个想法是用整数进行所有计算并推迟除法。

在执行除法之前添加一半的分母(否则你会在除法中截断,因此因为100%-x而得到上舍入)

例如,A = 9且B = 11,百分比为18.18181818 ......并且舍入18.18,没有舍入的计算将得到1819而不是预期结果1818。

请注意,计算是以整数形式完成的,因此对于AB的较大值存在溢出的风险。例如,如果int是32位,那么A可以达到大约200000,然后在计算A*10000时冒着溢出的风险。

在公式中使用A*10000LL代替A*10000会以一定的速度进行交易,以将限制提高到更大的值。

答案 1 :(得分:2)

当然,浮点数可能会出现精确损失。您应该使用固定点数作为@ 6502应答,或者为结果添加偏差以获得预期答案。 你应该做得更好

assert(B != 0);
int percentage = ((A<0) == (B<0) ? 0.5 : -0.5) + (((1 - (double)A/B) / 0.01)) * 100;

由于精度损失,(((1 - (double)A/B) / 0.01)) * 100的结果可能略低于或超过预期。如果您添加额外的0.5,则可以保证比预期更多。现在,当您将此值转换为整数时,您将得到预期的答案。 (地板或ceil值取决于方程结果的小数部分是高于还是低于0.5)

答案 2 :(得分:0)

我试过

float floatpercent = (((1 - (double)A/B) / 0.01)) * 100;
int percentage = (int) floatpercent;
cout<< percentage;

显示1000

我怀疑将自动转换为int的精度损失作为代码的根本问题。

答案 3 :(得分:0)

[我在对原始问题的评论中提到了这一点,但我发布了它作为答案。]

核心问题是,当表示10的简单分数时,您使用的表达形式会放大不可避免的浮点精度损失。

你的表达(暂时删除了强制转换,使用标准优先级来避免一些parens)

((1 - A/B) / 0.01) * 100
尽管代数正确,

是表达你想要的东西的一种非常复杂的方式。不幸的是,浮点数只能精确地表示数字,如1 / 2,1 / 4,1 / 8等,它们的倍数,以及它们的总和。特别是,9/10或1/10或1/100都没有精确的表示。

上面的表达式引入了两次这些错误:首先是A/B的计算,然后是0.01的除法。然后将这两个不精确的值分开,这进一步放大了固有误差。

写出你的意思最直接的方式(再次没有需要演员)是

((B-A) / B) * 10000

这会产生正确的答案,我会建议,比原来更容易阅读。完全正确的C形式是

((B - A) / (double)B) * 10000

我已经对此进行了测试,并且可靠地运行。正如其他人所指出的那样,使用双打而不是花车通常会更好,因为它们的额外精度使它们不太容易(但不能免疫)这种困难。