2009-04-29 39 views
7

問題是,爲什麼這些代碼片段會給出不同的結果?簡單的計算,c#和delphi中的不同結果

private void InitializeOther() 
{ 
    double d1, d2, d3; 
    int i1; 

    d1 = 4.271343859532459e+18; 
    d2 = 4621333065.0; 
    i1 = 5; 

    d3 = (i1 * d1) - Utils.Sqr(d2); 
    MessageBox.Show(d3.ToString()); 
} 

procedure TForm1.InitializeOther; 
var d1, d2, d3 : Double; 
    i1 : Integer; 
begin 
    d1:=4.271343859532459e+18; 
    d2:=4621333065.0; 
    i1:=5; 

    d3:=i1*d1-Sqr(d2); 
    ShowMessage(FloatToStr(d3)); 
end; 

德爾福代碼給了我816,而C#代碼給了我0.1使用計算器,我得到775可有人請給我一個詳細的解釋?

非常感謝!

+1

Utils.Sqr中的錯誤也許? – 2009-04-29 15:58:47

+5

這是一個「簡單計算」?不是浮點數不是。 – 2009-04-29 16:07:41

+3

如果您將Delphi類型從double更改爲extended,則答案爲776,這證明了四捨五入的意思。如果您打算處理這麼大的fp數字,您可能需要查看一個bignum庫或其他科學圖書館。 – 2009-04-29 16:24:33

回答

11

Delphi將中間值存儲爲Extended(一個80位浮點類型)。此表達式是擴展的:

i1*d1-Sqr(d2); 

C#(我不知道)也可能不是這樣。額外的精度可能會有所作爲。

10

注意,你是在雙數據精度的極限在這裏輸入,這意味着這裏的計算將是不準確的。

實施例:

d1 = 4.271343859532459e+18 

這可以說是一樣的:

d1 = 4271343859532459000 

等:

d1 * i1 = 21356719297662295000 
實際上

,在.NET的值將是更多類似這樣:

2.1356719297662296E+19 

注意那裏的四捨五入。因此,在這個層面上,你沒有得到正確的答案。

0

我認爲這是由有限精度引起的錯誤(尤其是因爲使用雙精度而不是整數)。也許d1在作業後不一樣。因爲它大於2^32,d2 * d2肯定會與正確的值不同。

由於5 * d1甚至大於2^64,即使使用64位整數也無濟於事。您必須使用bignums或128位整數類才能獲得正確的結果。

+0

計算將在浮點域中執行,整數類型的範圍甚至不會在這裏發揮作用。 – mghie 2009-04-29 16:08:48

4

C#double最多有16位精度。以4.271343859532459e + 18乘以5將給出19位數字。你想要一個只有3位數的數字。 Double不能這樣做。

在C#中,Decimal類型可以處理此示例 - 如果您知道使用123M格式來初始化Decimal值。

Decimal d1, d2, d3; 
    int i1; 
    d1 = 4.271343859532459e+18M; 
    d2 = 4621333065.0M; 
    i1 = 5; 
    d3 = (i1 * d1) - (d2*d2); 

    MessageBox.Show(d3.ToString()); 

這給出了775.00這是正確的答案。

0

基本上,正如其他人所指出的那樣,雙精度對於您試圖執行的計算規模來說不夠精確。 Delphi默認使用「擴展精度」,這比Double增加了另外的16位,以允許更精確的計算。 .NET框架沒有擴展精度的數據類型。

不知道你的計算器正在使用什麼類型,但它顯然是做一些不同於Delphi和C#的東西。

0

正如其他人所評論的,雙精度對於您的計算來說不夠精確。 小數點是一個很好的選擇,但有人指出它會被四捨五入,事實並非如此。

在C#,十進制類型不能容易地處理該實施例中任一自4.271343859532459e + 18將被舍入到4271343859532460000.

這不是這種情況。如果你使用小數的答案是正確的。但正如他所說,範圍是不同的。