一尘不染

迭代边界与数据类型的相同

go

我拥有的函数采用 minmax 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解决方案
,但这似乎增加了不必要的开销。那是真的吗?


阅读 239

收藏
2020-07-02

共1个答案

一尘不染

例如,对于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

附录

这是我对DaveC的建议

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
2020-07-02