feat(utils): 新增快速平方根算法实现,包含卡马克算法及性能测试
This commit is contained in:
63
common/utils/sqrt.go
Normal file
63
common/utils/sqrt.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// fastInvSqrt 实现了卡马克的快速平方根倒数算法
|
||||||
|
func fastInvSqrt(x float32) float32 {
|
||||||
|
xhalf := float32(0.5) * x
|
||||||
|
i := math.Float32bits(x) // 将浮点数转换为32位整数
|
||||||
|
i = 0x5f3759df - (i >> 1) // 神奇数字和位操作
|
||||||
|
y := math.Float32frombits(i) // 将整数转换回浮点数
|
||||||
|
y = y * (float32(1.5) - xhalf*y*y) // 牛顿迭代一步提高精度
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
// fastSqrtCarmack 使用卡马克算法计算平方根
|
||||||
|
func fastSqrtCarmack(x float64) float64 {
|
||||||
|
if x == 0 || math.IsNaN(x) || math.IsInf(x, 1) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
if x < 0 {
|
||||||
|
return math.NaN()
|
||||||
|
}
|
||||||
|
|
||||||
|
x32 := float32(x)
|
||||||
|
invSqrt := fastInvSqrt(x32)
|
||||||
|
return float64(x32) * float64(invSqrt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fastSqrt 使用快速平方根倒数算法计算平方根
|
||||||
|
func fastSqrt(x float64) float64 {
|
||||||
|
// 处理特殊情况
|
||||||
|
if x == 0 || math.IsNaN(x) || math.IsInf(x, 1) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
if x < 0 {
|
||||||
|
return math.NaN()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为float32进行卡马克算法计算
|
||||||
|
x32 := float32(x)
|
||||||
|
invSqrt := fastInvSqrt(x32)
|
||||||
|
|
||||||
|
// 转回float64并计算平方根
|
||||||
|
result := float64(x32) * float64(invSqrt)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// fastSqrtInt 实现了针对整数的快速平方根算法
|
||||||
|
func fastSqrtInt(n int) int {
|
||||||
|
if n < 0 {
|
||||||
|
return 0 // 处理负数情况
|
||||||
|
}
|
||||||
|
if n == 0 || n == 1 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用浮点数版本的快速平方根
|
||||||
|
x := float64(n)
|
||||||
|
sqrt := fastSqrt(x)
|
||||||
|
return int(sqrt + 0.5) // 四舍五入转换为整数
|
||||||
|
}
|
||||||
91
common/utils/sqrt_test.go
Normal file
91
common/utils/sqrt_test.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_fastSqrt(t *testing.T) {
|
||||||
|
// 测试用例
|
||||||
|
testCases := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
||||||
|
|
||||||
|
fmt.Println("测试卡马克快速平方根算法与标准库的对比:")
|
||||||
|
fmt.Println("数值\t快速算法结果\t标准库结果\t绝对误差")
|
||||||
|
fmt.Println("--------------------------------------------------------------")
|
||||||
|
|
||||||
|
for _, x := range testCases {
|
||||||
|
fastResult := fastSqrt(x)
|
||||||
|
stdResult := math.Sqrt(x)
|
||||||
|
error := math.Abs(fastResult - stdResult)
|
||||||
|
|
||||||
|
fmt.Printf("%.10g\t%.10g\t\t%.10g\t\t%.2e\n",
|
||||||
|
x, fastResult, stdResult, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试整数版本
|
||||||
|
fmt.Println("\n测试整数快速平方根算法:")
|
||||||
|
fmt.Println("数值\t快速算法结果\t标准库转换结果")
|
||||||
|
fmt.Println("--------------------------------------")
|
||||||
|
|
||||||
|
for _, x := range []int{2, 4, 10, 16, 25, 100, 1000} {
|
||||||
|
fastResult := fastSqrtInt(x)
|
||||||
|
stdResult := int(math.Sqrt(float64(x)))
|
||||||
|
|
||||||
|
fmt.Printf("%d\t%d\t\t%d\n", x, fastResult, stdResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func BenchmarkMathSqrt(b *testing.B) {
|
||||||
|
testValues := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, x := range testValues {
|
||||||
|
_ = math.Sqrt(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFastSqrt(b *testing.B) {
|
||||||
|
testValues := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, x := range testValues {
|
||||||
|
_ = fastSqrt(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFastSqrtCarmack(b *testing.B) {
|
||||||
|
testValues := []float64{2, 4, 10, 16, 25, 100, 1000, 0.5, 0.01, 1e-20}
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, x := range testValues {
|
||||||
|
_ = fastSqrtCarmack(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMathSqrtInt(b *testing.B) {
|
||||||
|
testValues := []int{2, 4, 10, 16, 25, 100, 1000, 10000, 100000}
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, x := range testValues {
|
||||||
|
_ = int(math.Sqrt(float64(x)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFastSqrtInt(b *testing.B) {
|
||||||
|
testValues := []int{2, 4, 10, 16, 25, 100, 1000, 10000, 100000}
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, x := range testValues {
|
||||||
|
_ = fastSqrtInt(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user