2012-12-08 60 views
7

爲什麼tan 45(弧度爲0.7853981633974483)給我0.9999?下面的代碼有什麼問題?棕褐色45給我0.9999

System.out.println(Math.tan(Math.toRadians(45.0))); 

我不認爲有任何錯字這裏。

那麼這裏有什麼解決方案?

+0

可能是舍入誤差。但是,如果它只顯示4位數字,它*應該舍入到1。 – Mysticial

+2

Python給了我'0.99999999999999989',無論我輸入它的位數是多少。這可能是浮點和逼近誤差。 – Blender

+0

您是否遺漏了任何數字? –

回答

16

浮點計算通常會導致這樣的不準確。問題是數字不能在固定位數內準確表示。

給你另一個例子(十進制),我們都同意3 * (1/3) = 1。但是,如果您的計算器只有4位小數,1/3將表示爲0.3333。當它乘以3時,您將獲得0.9999而不是1

如進一步的信息,在大多數系統的浮點是通常使用IEEE754標準表示。您可以搜索它,或參考維基百科頁面以獲取更多詳細信息。 IEEE floating point

+0

那麼解決方案是什麼? – siaooo

+1

@siaooo舍入到您需要的相關小數位數,對於tan(45),它將舍入爲1. –

+0

@ScottChamberlain ok謝謝 – siaooo

2

使用此

double radians = Math.toRadians(45.0); 

System.out.format("The tangent of 45.0 degrees is %.4f%n", Math.tan(radians)); 
+1

-1這個答案不能理解浮點運算是問題。將弧度轉換爲度數不是。 – 2012-12-08 10:09:00

+2

@woodchips我不認爲這個答案是聲稱將弧度轉換爲度是問題。然而,我認爲在某種程度上**將弧度轉換爲度數是問題**:如果我們對正確舍入的超越函數(我們沒有)進行標準化,那麼如果我們有一個接受度數的正切函數(我們沒有那麼這個函數的結果應用到45將是1.但是正確地舍入了我們有的弧度正切函數,我們沒有將它應用到π/ 4,而是應用到最接近的「double」,因此我們很難期望得到1回報。 –

+0

@woodchips此外,這個答案在轉換爲輸出**的十進制時截斷小數點**。這仍然把它放在「截斷二進制浮點數到固定小數位數」之上,你可以在StackOverflow上看到很多問題和答案。 –

0

這可能是因爲tan(45)爲1,其餘是一個舍入誤差。由於浮點計算的工作原理,浮點計算極不可能爲您提供準確的結果。

+3

這是因爲你正在*最接近的雙*的切線到pi/4。數學庫中的「tan」正確舍入。浮點計算的重點在於,如果您注意自己在做什麼,它們會走得很快,並且會*給您提供準確的結果。 – tmyklebu

10

最接近doublepi/4正是0x1.921fb54442d18p-1。這個雙倍的切線,比你需要的更多的比特是0x1.fffffffffffff72cece67p-1。舍入到最接近的double會給出的確切值0x1.fffffffffffffp-1,因爲0x1.fffffffffffff72cece67p-1小於0x1.fffffffffffff8p-1

+0

是的!一個合理的答案! Java是否指定了正確的舍入超越函數? –

+1

@PascalCuoq:Java不要求正確的四捨五入。它指定(查看API文檔,我認爲它是規範的)答案必須在正確結果的1 ulp以內,並且除非tan的極點是'x'和'y'之間的區別,Math.tan(x ) - Math.tan(y)'不具有與tan(x)-tan(y)相反的符號。 – tmyklebu

+0

快速的Google搜索讓我回到了經典的http://www.cs.berkeley.edu/~wkahan/LOG10HAF.TXT。值得重新閱讀。 –