c – 如何循环浮点数的精确表示?

我试图从一个浮点数到下一个完全循环.比如说,我需要从std :: numeric_limits< float> :: epsilon()循环到1,它们都是完全可表示的IEEE754数字.我的代码是:

 using nld = std::numeric_limits<float>;
 auto h = nld::epsilon();
 for (; h < 1; h = std::nextafter(h, 1)) {
     std::cerr << "h: " << h << std::endl;
 }

无限循环,因为h是完全可以表示的,所以nextafter不断返回它.我也知道在循环中将机器epsilon添加到h不会削减它:浮点数不是等间隔的.如何循环IEEE754数字的确切表示?

不等间距的问题出现在这里:

 using nld = std::numeric_limits<float>;
 auto h = nld::epsilon();
 for (; h < 4; h += nld::epsilon()) {
     if (h = h + nld::epsilon()) {
         std::cerr << "h: " << h << std::endl;
     }
 }

这为我保留了打印2

最佳答案 根据评论:

nextafter的方法正是你应该做的.但是,它有一些可能导致意外结果的并发症.

引用cppreference std::nextafter

float nextafter( float from, float to ); (1) (since C++11)
double nextafter( double from, double to ); (2) (since C++11)
long double nextafter( long double from, long double to ); (3) (since C++11)
Promoted nextafter( Arithmetic from, Arithmetic to ); (4) (since C++11)

4) A set of overloads or a function template for all combinations of arguments of arithmetic type not covered by (1-3). If any argument has integral type, it is cast to double. If any argument is long double, then the return type Promoted is also long double, otherwise the return type is always double.

由于你的to是1,类型为int,你得到重载版本4,返回类型为double.现在,完全有可能给定一个浮点数f,(浮点数)nextafter((double)f,1)与原始f完全相等:很可能,double类型中的下一个可表示数字不能用float表示,转换回浮动向下舍入.

返回float的唯一重载是float类型.要使用该重载,请使用1.0f而不是1.

点赞