2015-08-15 37 views
0

我試圖讓使用下面的代碼int數組的平均值:爲什麼我不能在Swift中減少內部整數?

let numbers = [1,2,3,4,5] 
let avg = numbers.reduce(0) { return $0 + $1/numbers.count } 
print(avg) // 1 

這顯然是不正確。但是,如果我刪除分工封閉外:

let numbers = [1,2,3,4,5] 
let avg = numbers.reduce(0) { return $0 + $1 }/numbers.count 
print(avg) // 3 

賓果!我想我還記得在某處讀過的東西(不能回想起它是否與Swift,JavaScript或編程數學有關),這與將長度除以長度產生一個浮點/雙倍的事實有關。 (1 + 2)/5 = 0.6這將在總和內舍入爲0。不過,我期望((1 + 2) + 3)/5 = 1.2返回1,但它也似乎返回0

隨着雙打,計算按預期工作無論怎樣它的計算,只要我箱的雙數整數

let numbers = [1.0,2.0,3.0,4.0,5.0] 
let avg = numbers.reduce(0) { return $0 + $1/Double(numbers.count) } 
print(avg) // 3 

我想我明白了爲什麼(也許不是?)。但我不能拿出一個可靠的例子來證明這一點。

任何幫助和/或解釋是非常讚賞。謝謝。

+0

int/int - > int':必須提升類型* first *做浮點除法。 – user2864740

回答

2

該部門不產生雙重;你在做整數除法。

你沒有得到((1 + 2) + 3 etc.)/5

在第一種情況下,您將獲得(((((0 + (1/5 = 0)) + (2/5 = 0)) + (3/5 = 0)) + (4/5 = 0)) + (5/5 = 1)) = 0 + 0 + 0 + 0 + 0 + 1 = 1

在第二種情況下,您得到((((((0 + 1) + 2) + 3) + 4) + 5)/5) = 15/5 = 3

在第三種情況下,雙精度損失比整數小得多,並且您得到類似(((((0 + (1/5.0 = 0.2)) + (2/5.0 = 0.4)) + (3/5.0 = 0.6)) + (4/5.0 = 0.8)) + (5/5.0 = 1.0))的東西。

+0

感謝您的輸入。那麼爲什麼當所有投入都是Ints時,2個減少案例會給出不同的結果? –

+0

@KyleGillen因爲'int/int - > int'。精度損失發生在*每減少*。 – user2864740

+0

@KyleGillen,因爲它們是不同的操作。 – muhmuhten

0

問題是,你正在試圖用第一段代碼沒有數學意義。

序列的平均值是整個序列除以元素數量的總和。

reduce爲正在調用的集合的每個成員調用lambda函數。因此,你正在總結和分開。

+1

該分區僅適用於$ 1(注意運算符優先級),並且累加器的初始值爲零,數學很好。 – muhmuhten

+0

好吧,如果使用合理的算術,數學*將會很好。正如我們所看到的,事實並非如此。 – muhmuhten

+0

謝謝@ andre-artus。在我腦海中出現的某個點上,所以我假設:(1 + 2)/ 5 = 0.6>(0.6 + 3)/ 5 = 0.72等,這確實可以解釋最高用例以1但是,在使用雙打的情況下 - 爲什麼它按預期工作? –

相關問題