长期的程序员 - 总计新手。
这是代码。这是我第一次尝试发电机。我正在尝试生成一个lfsr序列。从本质上讲,每次你都转右。如果您刚刚移出1
位,xor的值为tap
。
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())
}
}
我得到的打印输出是:
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
我做错了什么 - 为什么看起来不错?
Play - 有趣的是 - 它输出:
...
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
这是a)略有不同,b)表明fmt.Println("lfsr ", n.String())
是失败的,但我没有找到原因。
加
经过实验(将ten.SetString("10", 32)
更改为ten.SetString("10", 10)
),我现在得到:
lfsr 5
next 5 bit(0) 1
Tap!%!(EXTRA string=0)panic: runtime error: index out of range
现在去睡觉 - 希望有人可以提供帮助。
答案 0 :(得分:1)
它似乎是由big.Int上的String()实现引起的。你可以省略n
上的String()调用,让Println弄清楚如何打印参数本身:
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)
}
}
答案 1 :(得分:1)
复制big.Int
是不安全的。特别是解除引用*big.Int
并将其分配给值不起作用。底层数组是别名而不是复制。因为数组可以以打破不变量的方式进行变异
第ret := *next
行是您错误的来源。
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
复制big.Int
的方法是ret := *new(big.Int).Set(next)
。我认为应该有func Copy(n *big.Int) *big.Int
这样做,因为语法有点难看。另外,我会避免使用big.Int
作为值,并更改lfsr
以返回指针。