将浮点数向上舍入为整数,这有多可靠?

时间:2014-02-06 22:58:31

标签: c++ floating-point

之前我见过static_cast<int>(std::ceil(floatValue));

我的问题是,我是否可以完全指望这不是“不必要地”四舍五入?我已经读过一些完整的数字不能用浮点数来完美表示,所以我担心的是,微小的“错误”会在逻辑上不应该使ceil()向上舍入。不仅如此,但是一旦完成,我担心表示中的小“错误”可能导致数字略小于整数,导致转换为int以截断它。

这种担心是否没有根据?我记得有一段时间,在python中的一个例子,打印一个特定的整数将导致它打印一些非常少的东西(如x.999,虽然我不记得确切的数字)

我需要确定的原因是,我正在编写纹理缓冲区。常见的情况是整数作为浮点数,但它偶尔会在需要舍入到最接近的整数宽度和包含它们的高度的值之间得到。它以2的幂为单位递增,因此不必要地舍入的成本可能导致应该只采用256x256纹理需要512x512纹理。

3 个答案:

答案 0 :(得分:4)

如果floatValue是准确的,那么代码中的舍入就没有问题。唯一可能的问题是溢出(如果结果不适合int)。当然,如此大的值,float通常没有足够的精度来区分相邻的整数。

然而,危险通常在于floatValue本身并不准确。例如,如果它是某些计算的结果,其精确答案是整数,则由于计算中的浮点舍入误差,它可能会导致大于整数的微小数量。

因此,您是否遇到问题取决于您获得floatValue的方式。

答案 1 :(得分:2)

  

范围是0.0到~1024.0

此范围内的所有整数都可以完全表示为float,所以你会没事的。

只有在您偏离float提供的24 bits of mantissa之后,您才会开始遇到问题。

答案 2 :(得分:2)

  

我绝对可以指望这不是“不必要地”四舍五入吗?我读过一些完整的数字不能用浮点数完美表示,所以我担心的是,微小的“错误”会欺骗ceil()

是的,一些大数字不可能完全代表浮点数。在发生这种情况的区域中,所有浮点数都是整数。错误不是微不足道的:如果出现错误,浮点表示整数的错误至少为1。而且,显然,在某些整数不能表示为浮点且所有浮点数都是整数的区域中,ceil(f) == f

有问题的区域是| f | &GT; 2 24 (16 * 1024 * 1024)用于IEEE 754单精度和| f | &GT; 2 53 用于IEEE 754双精度。

您更有可能遇到的问题不是来自以浮点格式表示整数的可能性,而是来自舍入误差的累积影响。如果你的编译器提供IEEE 754语义,那么任何+,(现代和不那么现代英特尔处理器的SSE2指令准确地执行浮点标准) - ,*,/和导致一些浮动精确表示开方运算-point保证产生该结果,但如果您应用的几个操作没有完全可表示的结果,则浮点计算可能会偏离数学计算,即使最终结果是整数且可以准确表示。然后,您可能会得到一个略高于目标整数的浮点结果,并导致ceil()返回除了您通过精确数学计算获得的其他内容。

有一些方法可以确信某些浮点运算是准确的(因为结果总是可以表示的)。例如(double)float1 * (double)float2,其中float1float2是两个单精度变量,总是精确的,因为两个单精度数相乘的数学结果总是可以表示为{ {1}}。通过以“正确”的方式进行计算,可以最小化或消除最终结果中的错误。