Home >Backend Development >Golang >Golang uses Exp for big.Int in structure strangely changes value

Golang uses Exp for big.Int in structure strangely changes value

王林
王林forward
2024-02-12 14:00:07904browse

Golang 在结构体中使用 Exp for big.Int 奇怪地改变了值

Question content

Below, a has undergone an unexpected change. d is constructed using the value of a (*a), then d.c is changed correctly. But why is a changed to the first parameter of Exp?

type Decimal struct {
    c big.Int // coefficient
    q big.Int // exponent
}
a := big.NewInt(1)
b := big.NewInt(2)
d := Decimal{*a, *b}
d.c.Exp(big.NewInt(11), big.NewInt(2), big.NewInt(0))
fmt.Println(a, b, d) // 11 2 {{false [121]} {false [2]}}

I hope a remains the same.

Edit: To add, I also printed the pointer addresses of a, b, d.c, d.q, and in Exp Different before and after: fmt.Printf("%p %p %p %p \n", &a, &b, &d.c, &d.q)

Workaround

Here is a simpler example showing the same content:

x := big.NewInt(1)
y := *x
y.Exp(big.NewInt(11), big.NewInt(2), big.NewInt(0))
fmt.Println(x)  // 11
fmt.Println(&y) // 121

The first thing to consider is y.Exp "Set z = x**y mod |m| (i.e. m sign is ignored), and z is returned.";Therefore the value of y changes (as shown above).

To understand why the value of x is changed, you can start with the Documentation:

"Shallow copy" is exactly what y := *x above (or d := Decimal{*a, *b} in code) does. So the solution is to follow the advice above:

x := big.NewInt(1)
y := new(big.Int).Set(x) // Avoid shallow copy
y.Exp(big.NewInt(11), big.NewInt(2), big.NewInt(0))
fmt.Println(x) // 1
fmt.Println(y) // 121

(You can do something similar in the example).

To explain why this happens, you need to see big.Int is defined. This requires checking some documentation, but it boils down to (simplified!):

type Int struct {
    neg bool // sign
    abs []uint // absolute value of the integer
}

Therefore, making a shallow copy of it will cause the slices of both instances to share the same backing array (this may lead to unpredictable results when elements in the slice change).

In your example, when set has been run. An easier way to demonstrate this is:

x := big.NewInt(1)
y := *x
y.Set(big.NewInt(11))
fmt.Println(x)  // 11
fmt.Println(&y) // 11

The above is the detailed content of Golang uses Exp for big.Int in structure strangely changes value. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete