为了账号安全,请及时绑定邮箱和手机立即绑定

Go中的索引突然超出范围

Go中的索引突然超出范围

Go
鸿蒙传说 2021-06-02 17:54:02
我正在尝试实现一种算法来查找低于某个限制的所有素数。但是,当达到限制时,46350我突然收到一条out of range错误消息:panic: runtime error: index out of rangegoroutine 1 [running]:main.main()    /tmpfs/gosandbox-433...fd004/prog.go:16 +0x1a8任何帮助我指出这里有什么问题的帮助表示赞赏(这个神奇的数字46350是从哪里来的?)。要重现将以下代码放入googles 沙箱并取消注释limit++(或使用此链接):package mainfunc 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            }        }    }}
查看完整描述

3 回答

?
MM们

TA贡献1886条经验 获得超2个赞

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

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


查看完整回答
反对 回复 2021-06-07
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

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

            }

        }

    }

}


查看完整回答
反对 回复 2021-06-07
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

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

您应该为 使用更大的数据类型j

阅读维基百科上的整数


查看完整回答
反对 回复 2021-06-07
  • 3 回答
  • 0 关注
  • 287 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信