簡體   English   中英

舍入y = x * x到最近

[英]Round y=x*x to nearest

將除法結果舍入到最接近的整數非常簡單 但我試圖圍繞除法的結果,以便后續操作將給出最佳近似值。 最好的解釋是一個簡單的函數:

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

我們可以看到,低階項會影​​響最終結果中的多個位。

但是,這些術語中的每一個都應該適合原始類型而不會溢出。 因此,通過適當的移位和屏蔽,我們可以獲得所需的結果。

當然,如果您使用更大的類型,編譯器/硬件會為您完成所有操作,因此如果您有選項,您應該這樣做。

使用TYPE int表示“y”。 我想這可以解決目的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM