2012-05-24 52 views
1

我想從0所有質數的總和爲2 000 000F#總和爲Int32列表拋出算術運算導致溢出

這是我的代碼:

let getPrimesUpTo (x : System.Int32) = 
    let upperBound = Convert.ToInt32(Math.Sqrt(Convert.ToDouble(x))) 

    let allNumbers = ref [1..x] in  
    for div = 2 to upperBound do allNumbers := List.filter (fun num -> (num % div <> 0 || div >= num)) !allNumbers  
    allNumbers 

let sop = 
    let nums = !(getPrimesUpTo 2000000) 
    List.sum nums 

當我運行它,我得到:「算術運算導致溢出」

如果我不這樣做List.sum我得到的素數

回答

2

List.sum使用檢查過的運算符,這會導致溢出。您可以通過源

List.sum calls Seq.sum 
Seq.sum calls Checked.(+) 

Checked.(+)上溢拋出一個錯誤是在追。附註:這就是爲什麼List.Fold (+)快於List.sum

要解決這個問題,你就需要改變你的代碼,使用64位整數(應該是足夠大的),我也收拾雙之間的轉換和int

let getPrimesUpTo (x : int64) = 
    let upperBound = x |> float |>sqrt |> int64 

    let allNumbers = ref [1L..x]  
    for div in 2L..upperBound do allNumbers := List.filter (fun num -> (num % div <> 0L || div >= num)) !allNumbers  
    allNumbers 

let sop = 
    let nums = !(getPrimesUpTo 2000000L) 
    List.sum nums 

這種計算質數的方法效率很低。我已經寫了一些相當不錯的代碼來計算F#中的大量素數 - 看到這裏https://stackoverflow.com/a/8371684/124259

3

大概List.sum是要嘗試總結瓦爾名單你可以得到Int32的值......並且大概是2,000,000的質數總和大於Int32.MaxValue。我懷疑Int64會好起來的 - 所以請嘗試將Convert.ToInt32更改爲Convert.ToInt64

+0

雅,這可以工作,但可以'工作'與int32 – Omu

+0

工作,而且,我得到一個Int32數字列表,唯一的問題是List.Sum – Omu

+0

@ChuckNorris:不熟悉F#,你可以指定一個轉換作爲List.sum調用的一部分嗎?例如'List.sum nums Convert.ToInt64' –

相關問題