英文:
Golang weird big.Int behavior for small number of bits
问题
我正在尝试使用欧几里得方法计算两个数的最大公约数,并注意到了奇怪的行为。尽管我将数值传递给函数,但对于位数较低的数字(通常小于64),函数会修改这些数字。请问这是我的错误还是预期行为?你可以在这里的Golang playground示例中查看代码:Golang playground示例
我认为预期的行为是通过将值传递给函数不应该改变任何值。感谢任何帮助,我在过去一天的搜索中没有找到其他类似的情况。
英文:
I am trying to calculate the GCD of two numbers via the Euclidean method, and noticed weird behavior. Although I am passing the value of the number to the function, the numbers are modified by the function for numbers with low number of bits (usually less than 64). Could anyone clarify if this is a mistake on my behalf or is it expected behavior? You can check the code in the playground here: Golang playground example
I thought the expected behavior is that no values should be changed by passing them to my functions. Thanks for any help, I couldn't find any other occurrences like this in the last day of searching.
答案1
得分: 3
big.Int是一个包含nat的结构体,其中nat被定义为type nat []Word
。因此,虽然你确实在复制big.Int,但其中的切片实际上是一个浅拷贝(切片的底层存储是相同的)。
至于为什么更大的位宽没有出现这个问题,我不确定。
可能需要在某个地方进行重新分配,从而创建一个新的[]Word
,从而保留原始值。
这也可能是为什么标准库通常返回*big.Int的原因,因为值实际上是不可复制的。
这是一个正确复制big.Int值的版本在play上。关键区别是:
a := new(big.Int).Set(x)
b := new(big.Int).Set(y)
(并且在一般情况下使用指针作为值并不特别有用)
英文:
big.Int is a struct containing nat, which is defined as type nat []Word
so, while you are indeed copying the big.Int, the slice inside it is effectively a shallow copy (underlying storage for slice is same)
For why the bigger bit widths don't exhibit the problem, not sure.
Possibly it requires a reallocation somewhere and that creates a new []Word
thereby leaving the original in tact.
This is also probably why the stdlib generally returns *big.Int, since a value isn't really copyable
here's a version on play that properly copies the big.Int values.
The key difference being:
a := new(big.Int).Set(x)
b := new(big.Int).Set(y)
(and using pointers in general as values aren't particularly useful)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论