英文:
Iteration boundaries same as data type's
问题
我有一个函数,它接受 min、max 作为 uint16
类型的参数,并在某个地方对数字范围进行迭代。然而,如果 max 恰好是 2^16-1(这是一个有效的用例),那么溢出会破坏循环逻辑。下面是一个用 uint8
演示问题的示例代码:
package main
import "fmt"
func iter(min, max uint8) {
for i := min; i <= max; i++ {
fmt.Printf("%d, ", i)
}
}
func main() {
iter(0, 255)
}
如你所见,程序永远不会结束。在另一个问题中也提出了类似的问题,但解决方案正好展示了我遇到的同样问题。
我目前的想法是将循环变量转换为 uint32
,类似于这样:
package main
import "fmt"
func iter(min, max uint8) {
for i := uint16(min); i <= uint16(max); i++ {
fmt.Printf("%d, ", i)
}
}
func main() {
iter(0, 255)
}
然而,这似乎是一个笨拙的解决方案,对于 uint64
或任何最大的 uintN
类型都不适用。感觉我漏掉了一些非常基本的东西。有什么指导吗?
我知道 Brad Fitz 的 Iter 解决方案,但它似乎增加了不必要的开销。这也是真的吗?
英文:
A function I have takes min, max uint16
parameters and at some point iterates over the numeric range. However, if max happens to be 2^16-1 (and it is a valid use case), then overflow breaks the loop logic. Here is an example code demonstrating the problem with uint8
:
package main
import "fmt"
func iter(min, max uint8) {
for i := min; i <= max; i++ {
fmt.Printf("%d, ", i)
}
}
func main() {
iter(0, 255)
}
As you can see, the program never ends. A similar question was asked at another question but the solution exactly exhibits the same problem I have.
My thinking for now is to convert the loop variable to uint32
, similar to this:
package main
import "fmt"
func iter(min, max uint8) {
for i := uint16(min); i <= uint16(max); i++ {
fmt.Printf("%d, ", i)
}
}
func main() {
iter(0, 255)
}
However, this seems to be a clumsy solution, which is not going to work for uint64
or whatever biggest uintN
type. Feels like I am missing something very basic. Guidance?
I am aware of Brad Fitz's Iter solution, but it seems to add unneeded overhead. Is that true as well?
答案1
得分: 3
例如,对于uint8
,
package main
import "fmt"
func iter(min, max uint8) {
{
min, max := uint(min), uint(max)
for i := min; i <= max; i++ {
fmt.Printf("%d, ", i)
}
}
}
func main() {
iter(0, 255)
}
对于uint64
,
package main
import "fmt"
func iter(min, max uint64) {
for i := min; i <= max; i++ {
fmt.Printf("%d, ", i)
if i == max {
break
}
}
}
func main() {
iter(^uint64(0)-2, ^uint64(0))
}
输出:
18446744073709551613, 18446744073709551614, 18446744073709551615
附加说明:
这是我对Dave C的建议的版本。
package main
import "fmt"
func iter(min, max uint64) {
for i, next := min, min <= max; next; i, next = i+1, i < max {
fmt.Printf("%#016[1]x ", i)
}
fmt.Println()
}
func main() {
const maxUint64 = ^uint64(0)
iter(0, 3)
iter(10, 9)
iter(maxUint64-2, maxUint64)
}
输出:
0x0000000000000000 0x0000000000000001 0x0000000000000002 0x0000000000000003
0xfffffffffffffffd 0xfffffffffffffffe 0xffffffffffffffff
英文:
For example, for uint8
,
package main
import "fmt"
func iter(min, max uint8) {
{
min, max := uint(min), uint(max)
for i := min; i <= max; i++ {
fmt.Printf("%d, ", i)
}
}
}
func main() {
iter(0, 255)
}
For uint64
,
package main
import "fmt"
func iter(min, max uint64) {
for i := min; i <= max; i++ {
fmt.Printf("%d, ", i)
if i == max {
break
}
}
}
func main() {
iter(^uint64(0)-2, ^uint64(0))
}
Output:
18446744073709551613, 18446744073709551614, 18446744073709551615
Addendum:
Here's my version of Dave C's suggestion.
package main
import "fmt"
func iter(min, max uint64) {
for i, next := min, min <= max; next; i, next = i+1, i < max {
fmt.Printf("%#016[1]x ", i)
}
fmt.Println()
}
func main() {
const maxUint64 = ^uint64(0)
iter(0, 3)
iter(10, 9)
iter(maxUint64-2, maxUint64)
}
Output:
0x0000000000000000 0x0000000000000001 0x0000000000000002 0x0000000000000003
0xfffffffffffffffd 0xfffffffffffffffe 0xffffffffffffffff
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论