问题描述
我正在尝试为定点数实现 Fast Inverse Square Root,但我一无所获。
我试图遵循与文章完全相同的原则,除了不是以浮点格式 x = (-1) ^ s * (1 + M) * 2 ^ (E-127)
编写数字,而是使用格式 x = M * 2 ^ -16
,它是 32 位16 位十进制数和 16 位小数位的定点数。
问题是我找不到“魔法常数”的值。根据我的计算,它不存在,但我不是数学家,我认为我做错了一切。
求解Y = 1 / sqrt(x),我用了如下推理(不知道对不对)。
在原始代码中,我们有用于近似牛顿的 Y0 由下式给出:
i = 0x5f3759df - (i >> 1);
这意味着我们将得到一个浮点数:
y0 = (1 + R2 - M / 2) * 2 ^ (R1 - E / 2);
这是因为操作 >>
将指数和尾数除以 2,然后我们将数字作为整数进行减法。
按照文章中的步骤,我将x的格式设置为:
x = M * 2 ^ -16
为了执行相同的逻辑,我尝试将 Y0 定义为:
Y0 = (R2 - M / 2) * 2 ^ (R1 - (-16/2));
error = (Y - Y0) / Y
无论 R1 的值如何,我都可以通过移位操作来修正最终结果的指数值,从而在固定点得到正确的结果。
我哪里错了?
解决方法
这是不可能的。
快速逆 sqrt 是由于浮点表示,它已经将数字拆分为 2 的幂(指数)和重要的。
可以做到。
使用与浮点相同的技巧,可以将您的定点转换为 2^exp * x。给定uint32_t a
,uint8_t exp = bias- builtin_count_leading_zeros(a)
; uint32_t b = a << exp
,仔细选择了常量(和 a
的域),不会出现下溢或溢出。
因此,您实际上将拥有一个自定义浮点表示,它是为此特定目的量身定制的,至少省略了符号位,并且指数的位数尽可能多,也可能是 8。
>