Go/Golang: 如何从 big.Float 中提取最低有效数字?
Go/Golang: how to extract least significant digits from big.Float?
在 Go/Golang 中,我有一个 big.Float 类型的变量,其(任意)精度为 3,324,000,表示 1,000,000 位的十进制数。它是计算 pi 的迭代结果。
现在我想打印出最低有效的 100 位数字,即数字 999,900 到 1,000,000。
我尝试使用 fmt.Sprintf() 和 big.Text() 将变量转换为字符串。然而,这两个函数都消耗了大量的处理时间,当进一步提高精度时,这是不可接受的(许多小时甚至几天)。
我正在寻找一些提取变量最后 100(十进制)数字的函数。
在此先感谢您的支持。
标准库没有提供有效地 return 这些数字的函数,但您可以计算它们。
将您感兴趣的数字隔离出来打印出来效率更高。这避免了对一个非常大的数字进行过多的计算来确定每个单独的数字。
下面的代码展示了一种实现方式。您将需要确保您有足够的精度来准确生成它们。
package main
import (
"fmt"
"math"
"math/big"
)
func main() {
// Replace with larger calculation.
pi := big.NewFloat(math.Pi)
const (
// Pi: 3.1415926535897932...
// Output: 5926535897
digitOffset = 3
digitLength = 10
)
// Move the desired digits to the right side of the decimal point.
mult := pow(10, digitOffset)
digits := new(big.Float).Mul(pi, mult)
// Remove the integer component.
digits.Sub(digits, trunc(digits))
// Move the digits to the left of the decimal point, and truncate
// to an integer representing the desired digits.
// This avoids undesirable rounding if you simply print the N
// digits after the decimal point.
mult = pow(10, digitLength)
digits.Mul(digits, mult)
digits = trunc(digits)
// Display the next 'digitLength' digits. Zero padded.
fmt.Printf("%0*.0f\n", digitLength, digits)
}
// trunc returns the integer component.
func trunc(n *big.Float) *big.Float {
intPart, accuracy := n.Int(nil)
_ = accuracy
return new(big.Float).SetInt(intPart)
}
// pow calculates n^idx.
func pow(n, idx int64) *big.Float {
if idx < 0 {
panic("invalid negative exponent")
}
result := new(big.Int).Exp(big.NewInt(n), big.NewInt(idx), nil)
return new(big.Float).SetInt(result)
}
在 Go/Golang 中,我有一个 big.Float 类型的变量,其(任意)精度为 3,324,000,表示 1,000,000 位的十进制数。它是计算 pi 的迭代结果。 现在我想打印出最低有效的 100 位数字,即数字 999,900 到 1,000,000。
我尝试使用 fmt.Sprintf() 和 big.Text() 将变量转换为字符串。然而,这两个函数都消耗了大量的处理时间,当进一步提高精度时,这是不可接受的(许多小时甚至几天)。
我正在寻找一些提取变量最后 100(十进制)数字的函数。 在此先感谢您的支持。
标准库没有提供有效地 return 这些数字的函数,但您可以计算它们。
将您感兴趣的数字隔离出来打印出来效率更高。这避免了对一个非常大的数字进行过多的计算来确定每个单独的数字。
下面的代码展示了一种实现方式。您将需要确保您有足够的精度来准确生成它们。
package main
import (
"fmt"
"math"
"math/big"
)
func main() {
// Replace with larger calculation.
pi := big.NewFloat(math.Pi)
const (
// Pi: 3.1415926535897932...
// Output: 5926535897
digitOffset = 3
digitLength = 10
)
// Move the desired digits to the right side of the decimal point.
mult := pow(10, digitOffset)
digits := new(big.Float).Mul(pi, mult)
// Remove the integer component.
digits.Sub(digits, trunc(digits))
// Move the digits to the left of the decimal point, and truncate
// to an integer representing the desired digits.
// This avoids undesirable rounding if you simply print the N
// digits after the decimal point.
mult = pow(10, digitLength)
digits.Mul(digits, mult)
digits = trunc(digits)
// Display the next 'digitLength' digits. Zero padded.
fmt.Printf("%0*.0f\n", digitLength, digits)
}
// trunc returns the integer component.
func trunc(n *big.Float) *big.Float {
intPart, accuracy := n.Int(nil)
_ = accuracy
return new(big.Float).SetInt(intPart)
}
// pow calculates n^idx.
func pow(n, idx int64) *big.Float {
if idx < 0 {
panic("invalid negative exponent")
}
result := new(big.Int).Exp(big.NewInt(n), big.NewInt(idx), nil)
return new(big.Float).SetInt(result)
}