2

我正在尝试实现一种算法来查找低于某个限制的所有素数。但是,当达到限制时,46350我突然收到一条out of range错误消息:

panic: runtime error: index out of range

goroutine 1 [running]:
main.main()
    /tmpfs/gosandbox-433...fd004/prog.go:16 +0x1a8

任何帮助我指出这里有什么问题都值得赞赏(这个神奇的数字46350是从哪里来的?)。

要重现将以下代码放入谷歌沙箱并取消注释limit++(或使用此链接):

package main

func main() {
    limit := 46349
    //limit++
    sieved_numbers := make([]bool, limit)
    var j = 0
    var i = 2

    for ; i < limit; i++ {
        if !sieved_numbers[i] {
            for j = i * i; j < limit;j += i {
                sieved_numbers[j] = true
            }
        }
    }
}
4

3 回答 3

9

因为当i == 46349,j = i * i溢出并且你留下一个负数。循环条件仍然为真,但它超出了数组的边界,因此您会感到恐慌。

在嵌套循环中添加一个fmt.Println(i, j)作为第一条语句,并在本地机器上运行它(它会在沙箱上超时),你会看到它发生。

于 2013-04-04T21:38:40.987 回答
4

i*i = 2148229801i==46349. 2^31有符号的 32 位整数在变为负数之前只能达到 ~ (32 位 - 符号的 1 位)。具体来说,您的变量将采用 is 的(2^32)/2 - (46349^2)-746153

如果您想执行此计算,请尝试使用 unsigned int 或 int64。

package main

// import "fmt"

func main() {
    var limit uint
    limit = 46349
    limit++
    sieved_numbers := make([]bool, limit)
    var j uint = 0
    var i uint = 2

    for ; i < limit; i++ {
        if !sieved_numbers[i] {
            for j = i * i; j < limit; j += i {
                sieved_numbers[j] = true
            }
        }
    }
}

在操场上试试

于 2013-04-04T21:48:43.343 回答
2

i * i产生一个大于 32 位有符号整数的最大大小的数字。

您应该为j.

在维基百科上阅读整数

于 2013-04-04T21:39:35.930 回答