将带符号的单精度浮点数舍入到最接近的整数的有效方法是什么?

Puf*_*fin 3 floating-point rounding msp430

float input = whatever;
long output = (long)(0.5f + input);
Run Code Online (Sandbox Code Playgroud)

这对于我在 MSP430 上的应用程序来说是低效的,使用编译器提供的浮点加法支持库。

我在想,这种特殊的“最近整数”舍入可能有一个聪明的“技巧”,避免了简单的浮点加法,也许是通过直接“位旋转”浮点表示,但我还没有找到这样的。任何人都可以建议这样的技巧来舍入 IEEE 754 32 位浮点数吗?

nju*_*ffa 5

按位操作的转换很简单,下面的 C 代码演示了这一点。根据关于 MSP430 上数据类型的注释,代码假定int包含 16 位和long32 位。

我们需要float一种unsigned long尽可能有效地将 的位模式传输到 的方法。此实现union为此使用 a ,您的平台可能具有更高效的特定于机器的方式,例如内在方式。在最坏的情况下,用于memcpy()复制字节。

只有几种情况需要区分。我们可以检查float输入的指数字段以将它们分开。如果参数太大或为 NaN,则转换失败。在这种情况下,一种约定是返回最小的负整数操作数。如果输入小于 0.5,则结果为零。在消除这些特殊情况之后,我们剩下的就是那些需要少量计算才能转换的输入。

对于足够大的参数,afloat总是一个整数,在这种情况下,我们只需要将尾数模式移动到正确的位位置。如果输入太小而不能成为整数,我们将转换为 32.32 定点格式。然后舍入基于最高有效小数位,在平局的情况下,也基于最低有效整数位,因为平局必须舍入为偶数。

如果平局应该总是从零舍入,代码中的舍入逻辑简化为

r = r + (t >= 0x80000000UL);
Run Code Online (Sandbox Code Playgroud)

下面是float_to_long_round_nearest()实现上述方法的 ,以及详尽测试此实现的测试框架。

r = r + (t >= 0x80000000UL);
Run Code Online (Sandbox Code Playgroud)