确保浮动小于精确值

Ric*_*rdo 4 c++ floating-point precision rounding floating-point-precision

我想在C++中计算以下形式的总和

float result = float(x1)/y1+float(x2)/y2+....+float(xn)/yn
Run Code Online (Sandbox Code Playgroud)

xi,yi都是整数.结果将是实际值的近似值.至关重要的是,该近似值小于或等于实际值.我可以假设我的所有价值观都是有限的和积极的.我尝试使用nextf(,0),就像在此代码段中一样.

cout.precision( 15 );
float a = 1.0f / 3.0f * 10; //3 1/3
float b = 2.0f / 3.0f * 10; //6 2/3
float af = nextafterf( a , 0 );
float bf = nextafterf( b , 0 );
cout << a << endl;
cout << b << endl;
cout << af << endl;
cout << bf << endl;
float sumf = 0.0f;
for ( int i = 1; i <= 3; i++ )
{
    sumf = sumf + bf;
}
sumf = sumf + af;
cout << sumf << endl;
Run Code Online (Sandbox Code Playgroud)

正如人们可以看到正确的解决方案那样3*6,666... +3.333.. = 23,3333... 但是作为输出我得到:

3.33333349227905
6.66666698455811
3.33333325386047
6.66666650772095
23.3333339691162
Run Code Online (Sandbox Code Playgroud)

即使我的小数量小于它们应该代表的数量,它们的总和也不是.在这种情况下应用nextafterfsumf会给我23.3333320617676哪一个较小.但这总是有效吗?圆角误差是否可能变得如此之大以至于nextafterf仍然使我超出正确的值?

我知道我可以通过实现分数类并精确计算所有内容来避免这种情况.但我很好奇是否有可能用浮动来实现我的目标.

438*_*427 5

尝试将浮点舍入模式更改为FE_TOWARDZERO.

请参阅此处的代码示例

更改浮点舍入模式

  • @Ricardo:默认情况下,大多数编译器都会在舍入到最近的位置进行常量折叠.你需要用gcc指定`-frounding-math`(`#pragma STDC FENV_ACCESS ON`做*不*做伎俩).我甚至不确定`-frounding-math`是否完全有效...... (2认同)
  • @StillLearning:对于想要定向四舍五入的人,我不知道更好的解决方案.令人遗憾的是,编译器供应商并不关心正确实现他们的语言,而且如果你没有几个月的时间来学习编译器的内部工作能够做出贡献,那么除了像我这样在互联网上抱怨之外没有真正的追索权也是不幸的.但这似乎就是现在的生活方式. (2认同)