2014-03-04 54 views
1

當然, System.out.println(0.1); 輸出0.1。但是對於任意小數點總是這樣嗎? (排除的雙號本身。如,System.out.println(0.10000000000000000001);輸出0.1精度而導致的情況下)「System.out.println(DECIMAL)」是否始終在代碼中輸出相同的DECIMAL?

當我打System.out.println(DECIMAL);我認爲,DECIMAL被轉換成二進制(雙)和二進制轉換成十進制(以輸出小數點作爲字符串)


想想下面的轉換。

小數[D1] - >(CONVERSION1) - >二進制[B] - >(CONVERSION2) - >十進制[D2]

CONVERSION1

(的顯著位的範圍內雙倍)[D1]的最接近的二進制數被選擇爲[B]

例如[D1] 0.1 - > [B] 0x0.1999999999999a

CONVERSION2

[D2]是十進制數可以唯一區分[B],並且具有最小的位數。

例如[B] 0x0.1999999999999a - > [D2] 0.1

QUOTE Java7 API Double.toString(double d)

多少位必須被打印的米或一個小數部分?必須至少有一位數字來表示小數部分,並且除此之外還需要多少位數,但只需要多少位數來唯一地區分參數值和類型爲double的相鄰值。也就是說,假設x是由該方法對有限非零參數d產生的十進制表示所表示的精確數學值。那麼d必須是最接近x的double值;如果兩個double值都同樣接近x,那麼d必須是其中之一,d的有效數字的最低顯著位必須爲0


我的問題

「[D1] = [D2]」是否總是正確的?


爲什麼我問這個問題

思考下面的情況,

節省用戶的十進制輸入作爲雙 - >顯示的是十進制

我想知道是否保證[用戶輸入=顯示]。

(如上所述,排除由雙數本身的精度導致的情況。因爲那很長的輸入是罕見的情況。)

我知道當我需要精確的算術時,我應該使用BigDecimal。但在這種情況下,我不需要精確的算術。只想顯示與用戶輸入相同的小數點。

+0

聽起來像你一路都知道,但你想要你的方式! :)但它會很有趣,看到它的一些答案。 – sakura

+0

我已經讀過兩遍你的問題,但我仍然不明白你的問題。 –

回答

0

第一次從十進制轉換爲二進制可能會產生另一個數學值,因爲不是每個小數都可以精確地表示爲二進制數。這與二進制的準確性無關,以0.1爲例。

從二進制到十進制的第二次轉換始終可以用無損耗的方式進行,即產生相同的數學值。這通常需要一個可笑的長十進制表示,所以在實踐中,你會將值四捨五入成爲一個更短的表示,這就不再是相同的數學值。

對您的問題的回答「是[D1] = [D2]總是正確的嗎?」因此一般沒有。這一切都取決於二進制和十進制表示的準確性。

+0

是否存在不輸出相同小數的實際情況? –

+0

@idi_prog你的意思是特殊情況'System.out.println(DECIMAL)'? Fankly,我不知道。這需要仔細分析邊緣情況。我認爲,不同的產出很少。 – Henry

1

它部分取決於你對平等的定義。如果你需要確切的字符串匹配,答案是否定的。例如:

System.out.println(0.1e-1); 

打印

0.01 

現在假設 「相等」 表示十進制的值相等,從而使0.1e-10.01是相等的。

如果您將雙打限制爲少於16位重要小數位的正常數字(非低於正常值,溢出或下溢),則表示您是安全的。每個二進制小數的無窮小數可以精確地以double表示。要恢復原始文件,它必須是該文件集中最短的成員。這意味着它與相同或較短長度的兩個最接近的十進制數之間的差異必須足夠大以確保它們輪到不同的雙打。要獲得另一個相同或更短長度的小數,則需要更改原始數字的至少一個小數點。

如果兩個十進制數在2^54中相差超過一個部分,並且處於正常數字範圍內,則它們相距太遠而不能映射到相同的雙精度值。

System.out.println(0.123451234512345e-310); 

打印

1.2345123451236E-311 

即使輸入只有15顯著位數:

,因爲它們比正常數字精度要求不高這個道理​​並不適用於次正規數。