Golang中数组Z[64]的值为什么仍然是0/1

Golang中数组Z[64]的值为什么仍然是0/1

// task1 project main.go

package main

import (

"fmt"

"math/big"

//"os"

//"strconv"

)

//var b [64]big.Rat

func GFS(z [64]big.Rat, c big.Rat, y [6]uint, w [6]uint, count uint) {

var temp big.Rat

switch count {

case 0:

if y[0] == 1 && y[1] == 1 {

temp.Mul(&c, big.NewRat(14, 15))

w[1] = 1

GFS(z, temp, y, w, 1+count)

temp.Mul(&c, big.NewRat(1, 15))

w[1] = 0

GFS(z, temp, y, w, 1+count)

} else {

w[1] = y[1]

GFS(z, c, y, w, 1+count)

}

case 1:

if y[2] == 1 && y[3] == 1 {

temp.Mul(&c, big.NewRat(14, 15))

w[3] = 1

GFS(z, temp, y, w, 1+count)

temp.Mul(&c, big.NewRat(1, 15))

w[3] = 0

GFS(z, temp, y, w, 1+count)

} else {

w[3] = y[3]

GFS(z, c, y, w, 1+count)

}

case 2:

if y[4] == 1 && y[5] == 1 {

temp.Mul(&c, big.NewRat(14, 15))

w[5] = 1

GFS(z, temp, y, w, 1+count)

temp.Mul(&c, big.NewRat(1, 15))

w[5] = 0

GFS(z, temp, y, w, 1+count)

} else {

w[5] = y[5]

GFS(z, c, y, w, 1+count)

}

case 3:

var m uint

for i := uint(0); i < 6; i++ {

m += w[i] << i

}

//fmt.Printf(z[m].String())

temp.Mul(&c, big.NewRat(1, 63))

z[m].Add(&z[m], &temp)

default:

break

}

}

func main() {

var z [64]big.Rat

var y [6]uint

var w [6]uint

var c = *big.NewRat(1, 1)

for i := 1; i < 64; i++ {

z[i] = *big.NewRat(0, 1)

}

for i := uint(1); i < 64; i++ {

y[0] = i & 0x1

y[1] = i & 0x2 >> 1

y[2] = i & 0x4 >> 2

y[3] = i & 0x8 >> 3

y[4] = i & 0x10 >> 4

y[5] = i & 0x20 >> 5

w[0] = y[0]

w[2] = y[2]

w[4] = y[4]

GFS(z, c, y, w, 0)

//fmt.Println(y)

}

for i := 0; i < 64; i++ {

fmt.Printf(z[i].String())

fmt.Println()

}

}

为什么数组 Z[64] 的值仍然是 0/1

TIM图片20180820094204


更多关于Golang中数组Z[64]的值为什么仍然是0/1的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

因为 64 不小于 64。

更多关于Golang中数组Z[64]的值为什么仍然是0/1的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言(以及其他编程语言中)中,数组的索引从0开始。因此,如果你声明一个数组 a[64] int,你将得到一个包含0到63个元素的数组。

在您的代码中,数组 z [64]big.Rat 的值保持为 0/1 的原因是由于 big.Rat 类型的初始化和在递归函数 GFS 中传递数组的方式导致的。以下是关键问题分析:

  1. 数组传递方式:在 Go 中,数组是值传递的。当您将数组 z 传递给 GFS 函数时,函数接收的是数组的副本,而不是原始数组的引用。因此,在 GFS 函数中对 z 的任何修改(例如 z[m].Add(&z[m], &temp))都只影响副本,不会改变 main 函数中的原始数组 z。这导致所有计算后的值无法反映到原始数组中,因此 z 保持初始的 0/1 值。

  2. 初始化问题:在 main 函数中,您通过循环将 z 的元素初始化为 0/1(即 big.NewRat(0, 1))。由于上述传递问题,这些初始值从未被更新。

  3. 递归调用中的数组副本:每次递归调用 GFS 时,都会传递数组 z 的新副本,修改仅作用于当前副本,最终丢失。

为了修复这个问题,您应该使用切片(slice)或指针来传递数组,以确保修改在原始数组上生效。以下是修改后的代码示例,使用切片来避免值传递问题:

package main

import (
    "fmt"
    "math/big"
)

// 修改 GFS 函数以接收切片而不是数组
func GFS(z []big.Rat, c big.Rat, y [6]uint, w [6]uint, count uint) {
    var temp big.Rat
    switch count {
    case 0:
        if y[0] == 1 && y[1] == 1 {
            temp.Mul(&c, big.NewRat(14, 15))
            w[1] = 1
            GFS(z, temp, y, w, 1+count)
            temp.Mul(&c, big.NewRat(1, 15))
            w[1] = 0
            GFS(z, temp, y, w, 1+count)
        } else {
            w[1] = y[1]
            GFS(z, c, y, w, 1+count)
        }
    case 1:
        if y[2] == 1 && y[3] == 1 {
            temp.Mul(&c, big.NewRat(14, 15))
            w[3] = 1
            GFS(z, temp, y, w, 1+count)
            temp.Mul(&c, big.NewRat(1, 15))
            w[3] = 0
            GFS(z, temp, y, w, 1+count)
        } else {
            w[3] = y[3]
            GFS(z, c, y, w, 1+count)
        }
    case 2:
        if y[4] == 1 && y[5] == 1 {
            temp.Mul(&c, big.NewRat(14, 15))
            w[5] = 1
            GFS(z, temp, y, w, 1+count)
            temp.Mul(&c, big.NewRat(1, 15))
            w[5] = 0
            GFS(z, temp, y, w, 1+count)
        } else {
            w[5] = y[5]
            GFS(z, c, y, w, 1+count)
        }
    case 3:
        var m uint
        for i := uint(0); i < 6; i++ {
            m += w[i] << i
        }
        temp.Mul(&c, big.NewRat(1, 63))
        z[m].Add(&z[m], &temp) // 现在修改会作用于原始切片
    default:
        break
    }
}

func main() {
    z := make([]big.Rat, 64) // 使用切片代替数组
    var y [6]uint
    var w [6]uint
    c := *big.NewRat(1, 1)

    // 初始化切片元素为 0/1
    for i := range z {
        z[i] = *big.NewRat(0, 1)
    }

    for i := uint(1); i < 64; i++ {
        y[0] = i & 0x1
        y[1] = i & 0x2 >> 1
        y[2] = i & 0x4 >> 2
        y[3] = i & 0x8 >> 3
        y[4] = i & 0x10 >> 4
        y[5] = i & 0x20 >> 5
        w[0] = y[0]
        w[2] = y[2]
        w[4] = y[4]
        GFS(z, c, y, w, 0) // 传递切片,修改会持久化
    }

    for i := 0; i < 64; i++ {
        fmt.Printf(z[i].String())
        fmt.Println()
    }
}

在这个修改版本中:

  • 我们将 z 从数组 [64]big.Rat 改为切片 []big.Rat,并使用 make 初始化。
  • GFS 函数现在接收一个切片参数,切片在 Go 中是引用类型,传递时不会复制底层数组,因此对 z[m] 的修改会直接影响 main 函数中的原始数据。
  • 其他逻辑保持不变,但现在 z 的值会在递归过程中正确更新,不再保持为 0/1

运行此代码后,z 数组的值将根据递归计算更新,显示非零分数结果。

回到顶部