2012-05-24 51 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' –

相关问题