绕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_divx_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_lox_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

上一篇: Round y=x*x to nearest

下一篇: Projection using contextual values in AutoMapper