我正在尝试编写一个在运行时执行以下计算的C函数:
分子/分母
其中:
分子是先前的计算结果,总是正数,并且大于分母
和
分母是这样的(1 <= Denominator&lt; = 64)。
运行时计算必须快速,即最少的周期,因此除法运算符是不可能的。我已经看过递归减法和按位长除法,但我试图找到另一种解决方案。
任何帮助?
答案 0 :(得分:1)
这是一个想法,它使用一个乘法和一个移位,因此它在大多数系统上比分割更快。由于你的分子在768,000,000~ = 30位时最高,我们在32位字中没有多少空间,所以我们必须使用64位乘法。
主要想法是利用以下事实:
x / y == (x * k) / (y * k)
除以2的幂是一个简单,快速的位移。
所以,为了选择一个特定的例子,假设x = 700,000,000
和y = 47
(所以正确的商是14,893,617)。为了避免舍入误差,我们的偏移需要大约是我们最大可能分子的大小--30位。找到k
的值,该值最接近y * k = 2^30
,在这种情况下为k = 22845571
。然后是x * k = 0x38D08C4CE6F500
。将此值移位30位得出0xE34231 = 14,893,617
,即我们的预期商。对于某些分子/分母组合,您可能需要再添加1-2位以进行舍入,除非在您的商中被1除掉是可以接受的。
然后,练习将创建一个查找表,其中包含每个可能分母的正确乘数。
编辑:正如下面的评论所指出的,选择k = (2^30 + y - 1) / y
应该提供比k = round(2^30 / y)
更好,更一致的结果。
答案 1 :(得分:0)
Big @ss表适用于小数字:
unsigned int divTable[kMaxNumerator][64] = {...}
你把每个可能的鸿沟的价值放在那里。在某些尺寸之上不太实用,但它确实适用于包含的情况,并且是当天的纹理映射的常见解决方案:)然后我读了你的评论,看到你在768,000,000范围内,这是因为完全不切实际,除非你可以处理相当多的精确损失。