什么规则控制将static_cast<float>应用于双精度的舍入行为?
如果我们在 C++ 中有一个双精度值并对其进行 astatic_cast<float>处理,返回值的绝对值是否总是较小?我的直觉在这背后说是的,原因如下。
- 可能的单精度指数集严格是双精度指数的子集
- 在将双精度尾数转换为单精度时,位可能会被截断然后结束以使双精度尾数适合浮点数尾数。但是,如果四舍五入更准确,有时会将其向上舍入到下一个最高浮点值并非不可能。也许这取决于系统,或者在某些标准中定义。
我在以下程序中对此进行了一些数值实验。似乎有时会发生向上取整,而其他时候则向下取整。
在哪里可以找到有关如何期望此舍入行为的更多信息?它是否总是四舍五入到最近的浮点数?
#include <cmath>
#include <iostream>
int main() {
// Start testing double precision values starting at x, going up to max
double x = 0.98;
constexpr double max = 1e10;
// Loop over many possible double-precision values, print out
// if casting to float ever produced a larger number.
int output_counter = 0; // output every n steps
constexpr int output_interval = 100000000;
std::cout.precision(17);
while (x < max) {
// volatile to ensure compiler doesn't optimize this out
volatile float xprime = static_cast<float>(x);
double xprimeprime = static_cast<double>(xprime);
if (xprimeprime > x)
std::cout << "Found a round up! x=" << x << ", xprime = "<< xprime << std::endl;
// Go to the next higher double precision value
x = std::nextafter(x, std::numeric_limits<double>::infinity());
output_counter++;
if (output_counter == output_interval) {
std::cout << x << std::endl;
output_counter = 0;
}
}
}
回答
标准在[conv.double] 中说:
浮点类型的纯右值可以转换为另一种浮点类型的纯右值。如果源值可以在目标类型中精确表示,则转换的结果就是该精确表示。如果源值介于两个相邻的目标值之间,则转换的结果是这些值中任何一个的实现定义选择。否则,行为是未定义的。
请注意,使用<limits>标题,您可以通过std::numeric_limits<T>::round_style. 有关可能的值,请参阅[round.style]。(至少我假设浮点转换属于浮点运算。)
THE END
二维码