2013-11-22 155 views
5

讓,x是一個整數,y = x * x全角度的C++ sqrt函數精度

那麼保證sqrt(y) == x

例如,我可以肯定的是sqrt(25)sqrt(25.0)將返回5.0,不5.00000000034.999999998

+3

如果5不能完全代表,它怎麼可能?最好你可以希望的是它截斷爲5. – chris

+0

由於5是一個整數,它不應該完全表示嗎?我在某處讀取double可以精確地存儲整數範圍內的值。 –

+2

@RafiKamal:IEEE-754 64位雙精度浮點數可以準確地表示32位有符號和無符號整數的整個範圍而不會丟失。這隻在那種情況下支配類型轉換。它不管理計算'sqrt(x)'的浮點庫的精度。 –

回答

4

不,你不能保證。對於適合浮點類型尾數的動態範圍的整數及其正方形(對於典型的C/C++ double,爲2^53),您可能確定,但​​不一定能保證。

您應該避免浮點值和精確值之間的等值比較,特別是精確的整數值。浮點舍入模式和其他這樣的事情可以真正阻礙你。

您可能希望使用「比較範圍」來接受「近似相等」的結果,或者用整數重新計算算法。有多個StackOverflow問題涉及浮點相等比較。我建議你搜索它們並閱讀。

對於某一類的問題,我在這裏寫了一個替代的解決方案: Find n-th root of all numbers within an interval

該解決方案採取不同的辦法不是依靠棘手的浮點運算。

8

符合IEEE-754標準的允許執行基本操作錯誤(其中sqrt爲示例)的實現要求正確舍入值。
這意味着錯誤將小於1/2 ULP(最後一個單位)或基本上儘可能接近實際答案。

要回答你的問題,如果實際的答案完全可以由double表示,那麼你會得到確切的答案。

注意:這不是由C++標準保證的,而是由IEEE-754標準保證的,這對大多數人來說可能不是問題。

最終,一個簡單的測試應該爲你的目的就足夠了:

for(int i = 0; i < (int)std::sqrt(std::numeric_limits<int>::max()); i++) 
    { 
     assert((int)(double)i == i);//Ensure exactly representable, because why not 
     assert(std::sqrt((double)i*i) == i); 
    } 

如果通過,我看不出有任何理由擔心。

1

你應該可以很容易地蠻力搜索所有的值,最多2^26,但我相信答案是肯定的。在那之後,沒有。

用於平方根的數位教科書算法用餘數== 0結束,從而給出確切的結果。然後,如果浮點庫聲明ieee-754符合性,它也會通過任何其他方式給出這個值。