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

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

Iteration boundaries same as data type's

问题

我有一个函数,它接受 minmax 作为 uint16 类型的参数,并在某个地方对数字范围进行迭代。然而,如果 max 恰好是 2^16-1(这是一个有效的用例),那么溢出会破坏循环逻辑。下面是一个用 uint8 演示问题的示例代码:

  1. package main
  2. import "fmt"
  3. func iter(min, max uint8) {
  4. for i := min; i <= max; i++ {
  5. fmt.Printf("%d, ", i)
  6. }
  7. }
  8. func main() {
  9. iter(0, 255)
  10. }

如你所见,程序永远不会结束。在另一个问题中也提出了类似的问题,但解决方案正好展示了我遇到的同样问题。

我目前的想法是将循环变量转换为 uint32,类似于这样:

  1. package main
  2. import "fmt"
  3. func iter(min, max uint8) {
  4. for i := uint16(min); i <= uint16(max); i++ {
  5. fmt.Printf("%d, ", i)
  6. }
  7. }
  8. func main() {
  9. iter(0, 255)
  10. }

然而,这似乎是一个笨拙的解决方案,对于 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:

  1. package main
  2. import &quot;fmt&quot;
  3. func iter(min, max uint8) {
  4. for i := min; i &lt;= max; i++ {
  5. fmt.Printf(&quot;%d, &quot;, i)
  6. }
  7. }
  8. func main() {
  9. iter(0, 255)
  10. }

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:

  1. package main
  2. import &quot;fmt&quot;
  3. func iter(min, max uint8) {
  4. for i := uint16(min); i &lt;= uint16(max); i++ {
  5. fmt.Printf(&quot;%d, &quot;, i)
  6. }
  7. }
  8. func main() {
  9. iter(0, 255)
  10. }

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

  1. package main
  2. import "fmt"
  3. func iter(min, max uint8) {
  4. {
  5. min, max := uint(min), uint(max)
  6. for i := min; i <= max; i++ {
  7. fmt.Printf("%d, ", i)
  8. }
  9. }
  10. }
  11. func main() {
  12. iter(0, 255)
  13. }

对于uint64

  1. package main
  2. import "fmt"
  3. func iter(min, max uint64) {
  4. for i := min; i <= max; i++ {
  5. fmt.Printf("%d, ", i)
  6. if i == max {
  7. break
  8. }
  9. }
  10. }
  11. func main() {
  12. iter(^uint64(0)-2, ^uint64(0))
  13. }

输出:

  1. 18446744073709551613, 18446744073709551614, 18446744073709551615

附加说明

这是我对Dave C的建议的版本。

  1. package main
  2. import "fmt"
  3. func iter(min, max uint64) {
  4. for i, next := min, min <= max; next; i, next = i+1, i < max {
  5. fmt.Printf("%#016[1]x ", i)
  6. }
  7. fmt.Println()
  8. }
  9. func main() {
  10. const maxUint64 = ^uint64(0)
  11. iter(0, 3)
  12. iter(10, 9)
  13. iter(maxUint64-2, maxUint64)
  14. }

输出:

  1. 0x0000000000000000 0x0000000000000001 0x0000000000000002 0x0000000000000003
  2. 0xfffffffffffffffd 0xfffffffffffffffe 0xffffffffffffffff
英文:

For example, for uint8,

  1. package main
  2. import &quot;fmt&quot;
  3. func iter(min, max uint8) {
  4. {
  5. min, max := uint(min), uint(max)
  6. for i := min; i &lt;= max; i++ {
  7. fmt.Printf(&quot;%d, &quot;, i)
  8. }
  9. }
  10. }
  11. func main() {
  12. iter(0, 255)
  13. }

For uint64,

  1. package main
  2. import &quot;fmt&quot;
  3. func iter(min, max uint64) {
  4. for i := min; i &lt;= max; i++ {
  5. fmt.Printf(&quot;%d, &quot;, i)
  6. if i == max {
  7. break
  8. }
  9. }
  10. }
  11. func main() {
  12. iter(^uint64(0)-2, ^uint64(0))
  13. }

Output:

  1. 18446744073709551613, 18446744073709551614, 18446744073709551615

Addendum:

Here's my version of Dave C's suggestion.

  1. package main
  2. import &quot;fmt&quot;
  3. func iter(min, max uint64) {
  4. for i, next := min, min &lt;= max; next; i, next = i+1, i &lt; max {
  5. fmt.Printf(&quot;%#016[1]x &quot;, i)
  6. }
  7. fmt.Println()
  8. }
  9. func main() {
  10. const maxUint64 = ^uint64(0)
  11. iter(0, 3)
  12. iter(10, 9)
  13. iter(maxUint64-2, maxUint64)
  14. }

Output:

  1. 0x0000000000000000 0x0000000000000001 0x0000000000000002 0x0000000000000003
  2. 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:

确定