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

Rounding a float upward to an integer, how reliable is that?

本文关键字:整数 舍入      更新时间:2023-10-16

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

不过,我的问题是,我能绝对指望这不是"不必要的"取整吗?我读到一些整数不能用浮点完美地表示,所以我担心微小的"误差"会欺骗ceil()在逻辑上不应该向上取整。不仅如此,一旦四舍五入,我担心表示中的一个小"错误"可能会导致数字略小于整数,从而导致对int的强制转换将其截断。

这种担心是没有根据的吗?我记得不久前,python中的一个例子,打印一个特定的整数会导致它打印的东西稍微少一些(比如x.999,尽管我记不清确切的数字)

我需要确保的原因是,我正在编写一个纹理缓冲区。常见的情况是将整数作为浮点,但偶尔会在需要四舍五入到最接近的整数宽度和高度的值之间切换。它以2的幂为步长递增,因此不必要的四舍五入成本可能会导致原本只需要256x256纹理的东西需要512x512纹理。

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

然而,危险通常在于floatValue本身并不精确。例如,如果它是某个计算的结果,其确切答案是一个整数,那么由于计算中的浮点舍入误差,它最终可能会比一个整数大一小部分。

所以你是否有问题取决于你是如何得到floatValue的。

我能指望这不会"不必要"地取整吗?我读到一些整数不能用浮点完美地表示,所以我担心微小的"错误"会欺骗ceil()

是的,有些大数字不可能精确地表示为浮点数。在发生这种情况的区域中,所有浮点数都是整数。错误不是极小的:用浮点表示整数的错误,如果有错误,至少是一个。很明显,在一些整数不能表示为浮点的区域中,所有的浮点数都是整数,ceil(f) == f

所讨论的区域对于IEEE 754单精度为|f|>224(16*1024*1024),对于IEEE 754的双精度为|f |>253。

你更可能遇到的问题不是因为无法用浮点格式表示整数,而是因为舍入误差的累积影响。如果您的编译器提供IEEE 754(浮点标准完全由现代和不那么现代的英特尔处理器的SSE2指令实现)语义,那么任何+、-、*和sqrt运算都可以保证产生一个完全可以表示为浮点的数字,但如果您应用的几个运算没有完全可以表示的结果,浮点计算可能会偏离数学计算,即使最终结果是整数并且可以精确表示。然后,您可能会得到一个略高于目标整数的浮点结果,并导致ceil()返回与精确数学计算不同的结果。

有一些方法可以确保某些浮点运算是精确的(因为结果总是可以表示的)。例如,(double)float1 * (double)float2,其中float1float2是两个单精度变量,总是精确的,因为两个单精确度数字相乘的数学结果总是可以表示为double。通过以"正确"的方式进行计算,可以最大限度地减少或消除最终结果中的误差。

的范围为0.0到~102.40

这个范围内的所有整数都可以精确地表示为float,所以您不会有事。

只有当你偏离float提供的24位尾数时,你才会开始出现问题。