c++中的精确百分比
Accurate percentage in C++
给定2个数字,其中A <= B
说例如A = 9
和B = 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
会丢失一些精度
是否有一种方法可以避免在我的情况下失去精度?
似乎你正在寻找的公式是
int result = 10000 - (A*10000+B/2)/B;
其思想是用整数和延迟除法来完成所有的计算。
要进行四舍五入,在执行除法之前要加上分母的一半(否则在除法中会被截断,从而由于100%-x而导致四舍五入)
例如,A=9, B=11,百分比为18.18181818…然后将18.18舍入,不舍入的计算将得到1819,而不是预期的结果1818。
请注意,计算全部以整数进行,因此A
和B
的大值有溢出的风险。例如,如果int
是32位,那么A
可以在计算A*10000
时冒溢出风险之前高达200000左右。
在公式中使用A*10000LL
而不是A*10000
将以一定的速度将限制提高到更大的值
当然,浮点数可能存在精度损失。要么你应该使用固定点数字作为@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
,那么它肯定会比预期的稍微多一些。现在,当你将这个值转换为整数时,你会得到预期的答案。(下限或上限值取决于方程结果的小数部分是大于还是小于0.5)
我试过了
float floatpercent = (((1 - (double)A/B) / 0.01)) * 100;
int percentage = (int) floatpercent;
cout<< percentage;
显示1000
我怀疑自动转换为int时的精度损失是您代码的根本问题。
[我在对最初问题的评论中提到了这一点,但我想我应该把它作为一个答案贴出来。]
核心问题是,当表示10的简单分数时,您使用的表达式形式放大了不可避免的浮点精度损失。
你的表达式(现在去掉了强制转换,使用标准优先级来避免一些父级)
((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
我已经测试过了,它工作可靠。正如其他人所指出的那样,通常使用双精度数而不是浮点数更好,因为它们的额外精度使它们不太容易(但并非完全免疫)出现这种困难。
- 编写一个函数以使用 n 百分比的 CPU 使用率
- 获取 2 个数字之间的差异百分比
- 在一定范围内生成随机数,其中一定百分比为特定值
- 获得所需的最小射门次数,以便进球数超过射门数是给定的百分比
- 如何计算单个元素在向量<float>中所有元素之和中的百分比
- 如何在AMD视频卡上获得GPU负载百分比和GPU温度
- C++中的类/函数模板占用了我的二进制文件的百分比是多少?
- 使用C 来计算您的工作中出现字母及其百分比的次数
- 计算百分比 C++ 时产生的 inf%
- 选择C++地图中随机元素的百分比
- 在窗口中获取缩放百分比
- 值的百分比 0.0000001 .1000.
- 如何在 matr 内按一定百分比随机分配数字
- 如何使用百分比标记字符串
- 显示零值的变量百分比
- 百分比符号之后的C 星号
- C 的打印百分比
- C++:计算每次迭代期间的概率百分比
- 规格CPU基准测试中各种浮点操作的百分比
- _vsnprintf和_vsnprintf_s的格式字符串中的可用百分比字符