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

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

Iteration boundaries same as data type's

问题

我有一个函数,它接受 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 解决方案,但它似乎增加了不必要的开销。这也是真的吗?

英文:

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 &quot;fmt&quot;

func iter(min, max uint8) {
	for i := min; i &lt;= max; i++ {
		fmt.Printf(&quot;%d, &quot;, 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 &quot;fmt&quot;

func iter(min, max uint8) {
	for i := uint16(min); i &lt;= uint16(max); i++ {
		fmt.Printf(&quot;%d, &quot;, 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 &quot;fmt&quot;

func iter(min, max uint8) {
	{
		min, max := uint(min), uint(max)
		for i := min; i &lt;= max; i++ {
			fmt.Printf(&quot;%d, &quot;, i)
		}
	}
}

func main() {
	iter(0, 255)
}

For uint64,

package main

import &quot;fmt&quot;

func iter(min, max uint64) {
	for i := min; i &lt;= max; i++ {
		fmt.Printf(&quot;%d, &quot;, 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 &quot;fmt&quot;

func iter(min, max uint64) {
	for i, next := min, min &lt;= max; next; i, next = i+1, i &lt; max {
		fmt.Printf(&quot;%#016[1]x &quot;, 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 

huangapple
  • 本文由 发表于 2015年4月27日 00:06:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/29880038.html
匿名

发表评论

匿名网友

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

确定