爲什麼下面的程序打印它打印的內容?爲什麼C#中的浮點運算不精確?
class Program
{
static void Main(string[] args)
{
float f1 = 0.09f*100f;
float f2 = 0.09f*99.999999f;
Console.WriteLine(f1 > f2);
}
}
輸出是
false
爲什麼下面的程序打印它打印的內容?爲什麼C#中的浮點運算不精確?
class Program
{
static void Main(string[] args)
{
float f1 = 0.09f*100f;
float f2 = 0.09f*99.999999f;
Console.WriteLine(f1 > f2);
}
}
輸出是
false
浮點僅具有精度這麼多的位數。如果你看到f1 == f2,這是因爲任何差異都需要比32位浮點數更高的精度。
我建議你閱讀What Every Computer Scientist Should Read About Floating Point
最主要的是,這不只是淨:它在內存中的underlying system most every language will use to represent a float的限制。精度只有這麼遠。
當你考慮到它甚至不是基數十的時候,你也可以用相對簡單的數字獲得一些樂趣。例如,0.1是以二進制表示的重複小數。
在這種特殊情況下,這是因爲.09和.999999不能用精確的二進制表示(類似地,1/3不能用精確的十進制精度表示)。例如,0.111111111111111111101111基數2爲0.999998986721038818359375基數10.將1加到先前的二進制數值中,0.11111111111111111111基數2是0.99999904632568359375基數10.沒有精確到0.999999的二進制值。浮點精度也受分配用於存儲指數和尾數的小數部分的空間的限制。此外,與整數類型一樣,浮點也可以溢出其範圍,儘管其範圍大於整數範圍。
運行該位在Xcode調試C++代碼,
浮子myFloat = 0.1;
顯示myFloat的值爲0.100000001。它已關閉0.000000001。不是很多,但如果計算有幾個算術運算,那麼不精確可能會複雜化。
恕我直言,浮點的一個很好的解釋是介紹計算機組織與x86-64的彙編語言& GNU/Linux的由加利福尼亞州立大學的鮑勃·Plantz第14章在索諾瑪(已退休)http://bob.cs.sonoma.edu/getting_book.html。以下是基於該章節。
浮點類似於科學記數法,其中值存儲爲大於或等於1.0且小於2.0(尾數)的混合數,將某個冪(指數)乘以另一個數。浮點數使用基數2而不是基數10,但在Plantz給出的簡單模型中,爲了清晰起見,他使用基數10。設想一個系統,其中兩個存儲位置用於尾數,一個位置用於指數符號*(0代表+和1代表 - ),一個位置用於指數。現在加0.93和0.91。答案是1.8,而不是1.84。
9311表示0.93或9.3倍於-1的-1。
9111表示0.91或9.1倍於-1的-1。
確切的答案是1.84或1.84倍10到0,如果我們有5個職位,這將是18400,但是,只有四個職位,答案是1800或1.8的10倍到零或1.8 。當然,浮點數據類型可以使用四個以上的存儲位置,但位置數量仍然有限。(Plantz,op。cit。)。不僅精度受空間限制,而且「二進制小數值的精確表示僅限於兩個反函數的和。」(Plantz,前述引文)。
0.11100110(二進制)= 0.89843750(十進制)
0.11100111(二進制)= 0.90234375(十進制)
有一個在二進制小數0.9沒有確切表示。即使將這些分數拿出更多的地方也是行不通的,因爲你會在右邊重複1100次。
開始程序員經常看到浮點運算,因爲精度比整數多 。確實,即使增加兩個非常大的整數也會導致溢出。乘法使得它更可能是結果將是非常大的,因此,溢出。當使用兩個整數 時,C/C++中的/運算符會導致小數部分 丟失。但是,浮點表示有其自己的不準確性。 (Plantz,同上)
*在浮點數中,數字的符號和指數的符號都被表示出來。
你爲什麼不自己嘗試一下呢? – 2009-04-15 22:14:41
我試過了,我只想知道爲什麼我看到我所看到的。 – Prankster 2009-04-15 22:17:48