在Go中索引突然超出范围

huangapple go评论66阅读模式
英文:

Index suddenly out of range in Go

问题

我正在尝试实现一个找出小于某个限制的所有质数的算法。然而,当限制达到46350时,我突然收到一个“超出范围”的错误信息:

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
			}
		}
	}
}
英文:

I am trying to implement an algorithm to find all primes below a certain limit. However, when the limit reaches 46350 i suddenly get an out of range error message:

panic: runtime error: index out of range

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

Any help to point me to what is wrong here is appreciated (and were does this magic number 46350 come from?).

To reproduce drop the following code into googles sandbox and uncomment limit++ (or use this link):

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
			}
		}
	}
}

答案1

得分: 9

因为当 i == 46349 时,j = i * i 溢出,导致得到一个负数。循环条件仍然为真,但它超出了数组的边界,所以会出现 panic。

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

英文:

Because when i == 46349, j = i * i overflows and you're left with a negative number. The loop condition is still true, but it's outside the boundaries of the array, so you get a panic.

Add a fmt.Println(i, j) as the first statement in your nested loop, and run it on your local machine (it'll time out on the sandbox) and you'll see it happen.

答案2

得分: 4

i*i = 2148229801i==46349。一个有符号的32位整数在变为负数之前只能达到约 2^31 (32位 - 1位用于表示符号)。具体来说,你的变量将会取值为 (2^32)/2 - (46349^2),即 -746153

如果你想执行这个计算,可以尝试使用无符号整数或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
			}
		}
	}
}

在 playground 上试一试

英文:

i*i = 2148229801 when i==46349. A signed 32 bit integer can only reach ~2^31 (32 bits - 1 bit for the sign) before it becomes negative. Specifically, your variable would have taken on the value of (2^32)/2 - (46349^2) which is -746153.

If you'd like to perform this computation, try using an unsigned int or an int64.

package main

// import &quot;fmt&quot;

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

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

Try it on the playground

答案3

得分: 2

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

你应该为j使用一个更大的数据类型。

Wikipedia上阅读关于整数的内容。

英文:

i * i produces a number which is greater than the maxiumum size of a 32 bit signed integer.

You should use a larger data type for j.

Read about integers on Wikipedia

huangapple
  • 本文由 发表于 2013年4月5日 05:30:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/15822096.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定