绕y = x * x到最近
将除法结果舍入到最接近的整数非常简单。 但是我试图将分割的结果进行舍入,以便随后的操作能够给出最佳的近似值。 这最好通过一个简单的函数来解释:
const int halfbits = std::numeric_limits<unsigned int>::digits / 2;
unsigned x = foo(); // Likely big.
unsigned x_div = x >> halfbits; // Rounded down
unsigned y = x_div * x_div; // Will fit due to division.
我可以通过添加1<<(halfbits-1)
将x_div
舍x_div
到最近。 但由于x²不是一个线性函数,所以y一般不会被正确舍入。 是否有一种简单且更精确的方法来计算(x*x) >> (halfbits*2)
而不使用更大的类型?
我认为向3<<(halfbits-3)
添加3<<(halfbits-3)
可以提高舍入,但不能证明这是最好的解决方案。 另外,这可以推广为x?
编辑 :根据大众的需求,我冒昧地用纯算术术语“翻译”这个问题(这些C变化的事情都没有......)。
注意:此后所有分部都是整数除数,例如13/3将是4。
问题:我们无法计算x ^ 2,因为x很大,所以我们想计算(x ^ 2)/(2 ^ N)。
为此我们计算
x_div = x / sqrt(2 ^ N)
我们接着说:
y = x_div * x_div
然而,这个结果通常不足(x^2)/(2^N)
的确切值,而OP建议加上0.5 * sqrt(2 ^ N)或0.375 * sqrt(2 ^ N)以更好地近似结果...
正如Oli Charlesworth
的答案所表明的,通过将x^2
看作(x_hi + x_lo)^ 2,有更好的方法来获得实际价值。
而使用x_div
截断会导致最多1的错误量级,而x_div*x_div
错误可能会高达1<<(half_digits+2)
。
为了明白为什么,考虑我们可以如下表示这种平方(使用长时间复制):
x * x = (x_lo + x_hi) * (x_lo + x_hi)
= x_lo^2 + x_hi^2 + 2*x_lo*x_hi
其中x_lo
和x_hi
分别是x
的下半部分和上半部分。 随着一些漂亮的ASCII艺术,我们可以考虑这些所有排队:
MSB : : : LSB
+------+------+ : :
| x_hi^2 | : :
+-----++-----++-----+: :
: | 2*x_lo*x_hi |: :
: +------++-----++------+
: : | x_lo^2 |
: : +------+------+
:<----------->: : :
Our result
正如我们所看到的,低阶项影响最终结果中的多个比特。
但是,这些术语中的每一个都应该适合原始类型而不会溢出。 所以,通过适当的换挡和遮挡,我们可以得到理想的结果。
当然,如果你使用更大型的编译器/硬件,编译器/硬件会为你做这些,所以如果你有选择的话,你应该这样做。
对于“y”使用TYPE int。 我想这会解决目的。
链接地址: http://www.djcxy.com/p/70473.html