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

王林
Release: 2024-02-12 14:00:07
forward
857 people have browsed it

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]}}
Copy after login

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
Copy after login

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
Copy after login

(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
}
Copy after login

Therefore, making a shallow copy of it will cause the slices of both instances to share the same backing array < /a> (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
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!