2012-09-05 339 views
1

我需要將一個數字範圍劃分爲一些長度相同的段。但我無法決定哪種方式更準確。例如:哪種方式更準確?

double r1 = 100.0, r2 = 1000.0, r = r2 - r1; 
int n = 30; 
double[] position = new double[n]; 
for (int i = 0; i < n; i++) 
{ 
    position[i] = r1 + (double)i/n * r; 
    // position[i] = r1 + i * r/n; 
} 

這是關於(double)int1/int2 * doubleint1 * double/int2。哪種方法更準確?我應該使用哪種方式?

更新

下面的代碼將顯示差:

double r1 = 1000.0, r2 = 100000.0, r = r2 - r1; 
int n = 300; 
double[] position = new double[n]; 
for (int i = 0; i < n; i++) 
{ 
    double v1 = r1 + (double)i/n * r; 
    double v2 = position[i] = r1 + i * r/n; 
    if (v1 != v2) 
    { 
     Console.WriteLine(v2 - v1); 
    } 
} 
+0

在我看來,它應該是平等的。你爲什麼不嘗試一下,看看有什麼區別? –

+0

這是一個很好的問題。我相信會有區別,它依賴於域(double,int1和int2的範圍)。這裏的關鍵詞是丟失有效數字。 – amit

+0

@amit你能回答我的問題嗎?我可以接受嗎? – EFanZh

回答

1

免責聲明:所有數字,我要給作爲例子是不準確的,但顯示出發生了什麼幕後的原則。

讓我們來看看兩種情況:

(1)int1 = 1000, int2= 3, double = 3.0 第一種方法會給你:(1000.0/3) * 3 == 333.33333 * 3.0 == 999.999...
雖然第二會給(1000 * 3.0)/3 == 3000/3 == 1000
在這種情況下 - 第二種方法更準確

(2)int1 = 2, int2 = 2, double = Double.MAX_VALUE
第一個將產生(2.0/2) * Double.MAX_VALUE == 1 * Double.MAX_VALUE == Double.MAX_VALUE
雖然第二會給(2 * Double.MAX_VALUE)/2 - 這將導致(在Java中)是Infinity,我不知道什麼雙重標準,說這個情況下,如果可能會溢出或永遠無限 - 但它肯定是一個問題。
所以,在這種情況下 - 第一種方法更準確。如果integer s爲long秒或在doublefloat,因爲有不能被double s爲單位代表的長值,所以精度損失可能在這種情況下發生了較大的double

的事情可能會去比較複雜,在任何情況下 - 大double值不太準確。

結論:哪個更好是域特定。在某些情況下,第一種方法應該更好,有些則是第一種方法。這實際上取決於int1,int2double的值。
然而,AFAIK,雙精度操作的一般經驗法則是保持儘可能小的計算(不要創建龐大的數字,然後再減少它們,儘量縮短它們的大小)。這個問題被稱爲loss of significant digits

+0

+1,以獲得正確答案。必須在VS簽入後將其移除 – Habib

1

也不是特別快的,因爲編譯器或JIT過程可以重新排序無論如何對於效率的操作。

+0

這是非常真實的。在做出這些決定之前,您應該檢查NGen'd二進制文件的反彙編。 – Ani

+1

你確定乘法是合理的,就像在這篇文章中一樣http://stackoverflow.com/questions/6430448/why-doesnt-gcc-optimize-aaaaaa-to-aaaaaa –

+0

@Ralu對於兩個被乘數只是它。如果有更多條款,我同意。 – akton

0

也許我誤解了你的要求,但爲什麼循環內部的任何分割/乘法呢?也許這會得到相同的結果:

decimal r1 = 100.0m, r2 = 1000.0m, r = r2 - r1; 
int n = 30; 
decimal[] position = new double[n]; 

decimal diff = r/n; 
decimal current = r1; 

for (int i = 0; i < n; i++) 
{ 
    position[i] = current; 
    current += diff; 
} 
+1

這可能會導致錯誤。由於'差異'不準確,小的偏差可能加起來就是一個很大的錯誤。 – EFanZh

+0

嗯,即時消息不太確定(也許我沒有看到你的需求),你可以發佈一些示例值?或者是什麼時候你最終會得到比另一個大得多的例子? – musefan

+0

@FanZh:我還是不明白我的代碼會給你帶來什麼「大錯誤」。你可以爲我的代碼指定哪些輸入值,這會導致準確性問題? – musefan