![](/img/trans.png)
[英]Generic function to accurately round floating-point to the nearest multiple of 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_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
我們可以看到,低階項會影響最終結果中的多個位。
但是,這些術語中的每一個都應該適合原始類型而不會溢出。 因此,通過適當的移位和屏蔽,我們可以獲得所需的結果。
當然,如果您使用更大的類型,編譯器/硬件會為您完成所有操作,因此如果您有選項,您應該這樣做。
使用TYPE int表示“y”。 我想這可以解決目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.