dou47732 2016-02-23 03:34
浏览 18
已采纳

转到:附加big.Int循环以切片意外结果

The following Go program produces 1,2,3,4 in followed by 5,5,5,5. I was expecting 1,2,3,4 in both cases. What am I doing wrong?

package main

import (
    "fmt"
    "math/big"
)

func primesLessThan(n *big.Int) (primes []big.Int) {
    var one big.Int
    one.SetInt64(1)
    var i big.Int
    i.SetInt64(1)
    for i.Cmp(n) < 0 {
        fmt.Println(i.String())
        primes = append(primes, i)
        i.Add(&i, &one)
    }
    return
}

func main() {
    primes := primesLessThan(big.NewInt(5))
    for _, p := range primes {
        fmt.Println(p.String())
    }
}

Update: the following code snippet illustrates the unexpected side effects of the shallow copy described in the responses. The output of the following snippet is 3, 3

one := big.NewInt(1)
two := big.NewInt(2)

one = two // Shallow copy. Question: how do I do a deep copy?

one.SetInt64(3) // Side-effect: also changes two

fmt.Println(one.String())
fmt.Println(two.String())
  • 写回答

3条回答 默认 最新

  • duannaoye0732 2016-02-23 05:56
    关注

    It's because of the way the object stores its internal data.

    Take this example:

    package main
    
    import "fmt"
    
    type foo struct {
        value int
    }
    
    func bar() (r []foo) {
        var f foo
        for i := 0; i < 5; i++ {
            f.value = i
            r = append(r, f)
        }
        return
    }
    
    func main() {
        for _, v := range bar() {
            fmt.Println(v)
        }
    }
    

    The output will be the expected

    {0}
    {1}
    {2}
    {3}
    {4}
    

    The issue in your example is that big.Int stores its value in a slice, and slices are pointers. So when a copy of a big.Int is created, the new copy contains a new pointer to the same slice in memory. A shallow copies is created rather than a deep copy.

    See https://golang.org/src/math/big/int.go?s=388:468#L8 for how bit.Int is declared, then see https://golang.org/src/math/big/nat.go#L25 for how nat is declared.

    Here is a solution that uses big.Int

    package main
    
    import (
        "fmt"
        "math/big"
    )
    
    func primesLessThan(n *big.Int) (primes []big.Int) {
        var one big.Int
        one.SetInt64(1)
        var i big.Int
        i.SetInt64(1)
        for i.Cmp(n) < 0 {
            var result big.Int
            result.Set(&i)
            fmt.Println(result.String())
            primes = append(primes, result)
            i.Add(&i, &one)
        }
        return
    }
    
    func main() {
        primes := primesLessThan(big.NewInt(5))
        for _, p := range primes {
            fmt.Println(p.String())
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测