douba1067 2013-09-26 23:06
浏览 39
已采纳

不索引时如何获得“索引超出范围”

Long time programmer - total newbie in go.

Here's the code. It is my first attempt at a generator. I am trying to generate an lfsr sequence. Essentially, every time around you shift right one. If you just shifted out a 1 bit, xor with the tap value.

package main

import (
    "fmt"
    "math/big"
)

// lfsr returns an lfsr generator.
func lfsr(tap, start big.Int) func() big.Int {
    // Keep track of next.
    next := &start
    // The generator.
    return func() big.Int {
        // Remember where we are.
        ret := *next
        // Work out next.
        fmt.Println("next", next.String(), "bit(0)", next.Bit(0))
        // Is it currently odd?
        odd := next.Bit(0)
        // Shift right one.
        next = next.Rsh(next, 1)

        // If odd - tap!
        if odd != 0 {
            // Tap!
            next = next.Xor(next, &tap)
            fmt.Printf("Tap!", next.String())
        }

        // Return where we were.
        return ret
    }
}

func main() {
    ten := new(big.Int)
    ten.SetString("10", 32)
    f := lfsr(*ten, *ten)
    for i := 0; i < 10; i++ {
        n := f()
        fmt.Println("lfsr ", n.String())
    }
}

The printout I am getting is:

next 32 bit(0) 0
lfsr  16
next 16 bit(0) 0
lfsr  8
next 8 bit(0) 0
lfsr  4
next 4 bit(0) 0
lfsr  2
next 2 bit(0) 0
lfsr  1
next 1 bit(0) 1
Tap! 0
panic: runtime error: index out of range

What am I doing wrong - and why does it look right?

Play - Interestingly - it outputs:

...
next 1 bit(0) 1
Tap!%!(EXTRA string=0)panic: runtime error: index out of range

goroutine 1 [running]:
math/big.nat.string(0xc010045150, 0x1, 0x5, 0x12b23d0, 0xa, ...)
    go/src/pkg/math/big/nat.go:819 +0x67f
math/big.nat.decimalString(0xc010045150, 0x1, 0x5, 0x1, 0x1, ...)
    go/src/pkg/math/big/nat.go:731 +0x8f
math/big.(*Int).String(0x7f851e0eff40, 0xc010045150, 0x1)
    go/src/pkg/math/big/int.go:331 +0xfe
main.main()
    /tmpfs/gosandbox-94dce1ec_430947f1_6360662e_01c3d6ad_a7071d20/prog.go:41 +0x120

which is a) slightly different and b) suggesting that the fmt.Println("lfsr ", n.String()) is what is failing but I am no nearer working out why.

Added

After experimentation (changing ten.SetString("10", 32) to ten.SetString("10", 10)) I now get:

lfsr  5
next 5 bit(0) 1
Tap!%!(EXTRA string=0)panic: runtime error: index out of range

Going to sleep now - hope someone can help.

  • 写回答

2条回答 默认 最新

  • douhuo3696 2013-09-27 05:23
    关注

    It is not safe to copy big.Int. In particular dereferencing a *big.Int and assigning it to a value does not work. The underlying array is aliased instead of copied. as the array can mutate in ways that break the invariants.
    The line ret := *next is the source of your bug.

    http://play.golang.org/p/W_qOCDsO2A

    i := big.NewInt(1)
    j := *i
    fmt.Println("i:", *i, "j:", j) // i: {false [1]} j: {false [1]}
    i = i.Xor(i, i)
    fmt.Println("i:", *i, "j:", j) // i: {false []} j: {false [0]}
    //j's state has changed, it now violates the invariants
    j.String() //boom
    

    The way to copy a big.Int is ret := *new(big.Int).Set(next). I think there should be func Copy(n *big.Int) *big.Int that does this, as the syntax is a bit ugly. Also I would avoid using big.Int as a value at all and change lfsr to return a pointer.

    Working example http://play.golang.org/p/WEFRnGlU1H.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看