2020-07-28:已知sqrt (2)约等于 1.414,要求不用数学库,求sqrt (2)精确到小数点后 10 位。
福哥答案2020-07-28:
1.二分法。
2.手算法。
3.牛顿迭代法。基础是泰勒级数展开法。
4.泰勒级数法。
5.平方根倒数速算法,卡马克反转。基础是牛顿迭代法。
golang代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | package test28_sqrt import ( "fmt" "math" "strconv" "testing" ) const ( EPSINON = 0.0000000001 ) //go test -v -test.run TestSqrt func TestSqrt(t *testing.T) { f := 2.0 fmt.Printf( "%v 系统自带\r\n" , strconv.FormatFloat(math.Sqrt(f), 'f' , -1, 64)) fmt.Println( "--------------------------------------------" ) fmt.Printf( "%v 二分法结果\r\n" , strconv.FormatFloat(sqrtDichotomy(f), 'f' , -1, 64)) fmt.Printf( "%v 手算法\r\n" , strconv.FormatFloat(sqrtHand(f), 'f' , -1, 64)) fmt.Printf( "%v 牛顿迭代法结果\r\n" , strconv.FormatFloat(sqrtNewton(f), 'f' , -1, 64)) fmt.Printf( "%v 泰勒级数法结果\r\n" , strconv.FormatFloat(sqrtTaylor(f), 'f' , -1, 64)) fmt.Printf( "%v 64位平方根倒数速算法结果1,精度上不符合\r\n" , strconv.FormatFloat(sqrtRootFloat64(f), 'f' , -1, 64)) fmt.Printf( "%v 64位平方根倒数速算法结果2,精度上不符合\r\n" , strconv.FormatFloat(float64(InvSqrt64(f)), 'f' , -1, 64)) fmt.Println( "--------------------------------------------" ) f2 := float32(f) fmt.Printf( "%v 32位平方根倒数速算法结果1,精度上不符合\r\n" , strconv.FormatFloat(float64(sqrtRootFloat32(f2)), 'f' , -1, 64)) fmt.Printf( "%v 32位平方根倒数速算法结果2,精度上不符合\r\n" , strconv.FormatFloat(float64(InvSqrt32(f2)), 'f' , -1, 64)) } //二分法 func sqrtDichotomy(f float64) float64 { left := 0.0 right := f if f < 1 { right = 1 } mid := f / 2 //不写0.0的原因是for循环可能进不了,0值明显不对 mid_mid := 0.0 //mid*mid的值 for right-left > EPSINON { mid = (left + right) / 2.0 mid_mid = mid * mid if mid_mid > f { right = mid } else if mid_mid < f { left = mid } else { return mid } } return mid } //牛顿迭代法.基础是泰勒级数展开法 func sqrtNewton(f float64) float64 { z := 1.0 for math.Abs(z*z-f) > EPSINON { z = (z + f/z) / 2 } return z } //手算法 func sqrtHand(f float64) float64 { i := int64(f) ret := 0.0 //返回值 rettemp := 0.0 //大的返回值 retsinge := 0.5 //单个值 //获取左边第一个1,retsingle就是左边的第一个1的值 for i > 0 { i >>= 2 retsinge *= 2 } rettemp_rettemp := 0.0 for { rettemp = ret + retsinge rettemp_rettemp = rettemp * rettemp if math.Abs(rettemp_rettemp-f) > EPSINON { if rettemp_rettemp > f { } else { ret = rettemp } retsinge /= 2 } else { return rettemp } } } //泰勒级数展开法 func sqrtTaylor(f float64) float64 { correction := 1.0 for f >= 2.0 { f /= 4 correction *= 2 } return taylortemp(f) * correction } func taylortemp(x float64) float64 { //计算[0,2)范围内数的平方根 var sum, coffe, factorial, xpower, term float64 var i int sum = 0 coffe = 1 factorial = 1 xpower = 1 term = 1 i = 0 for math.Abs(term) > EPSINON { sum += term coffe *= 0.5 - float64(i) factorial *= float64(i) + 1 xpower *= x - 1 term = coffe * xpower / factorial i++ } return sum } //32位平方根倒数速算法1.卡马克反转。基础是牛顿迭代法。 func sqrtRootFloat32(number float32) float32 { var i uint32 var x, y float32 f := float32(1.5) x = float32(number * 0.5) y = number i = math.Float32bits(y) //内存不变,浮点型转换成整型 i = 0x5f3759df - (i >> 1) //0x5f3759df,注意这一行,另一个数字是0x5f375a86 y = math.Float32frombits(i) //内存不变,浮点型转换成整型 y = y * (f - (x * y * y)) y = y * (f - (x * y * y)) return number * y } //32位平方根倒数速算法2 func InvSqrt32(x1 float32) float32 { x := x1 xhalf := float32(0.5) * x i := math.Float32bits(xhalf) // get bits for floating VALUE i = 0x5f375a86 - (i >> 1) // gives initial guess y0 x = math.Float32frombits(i) // convert bits BACK to float x = x * (float32(1.5) - xhalf*x*x) // Newton step, repeating increases accuracy x = x * (float32(1.5) - xhalf*x*x) // Newton step, repeating increases accuracy x = x * (float32(1.5) - xhalf*x*x) // Newton step, repeating increases accuracy return 1 / x } //64位平方根倒数速算法1.卡马克反转。基础是牛顿迭代法。 func sqrtRootFloat64(number float64) float64 { var i uint64 var x, y float64 f := 1.5 x = number * 0.5 y = number i = math.Float64bits(y) //内存不变,浮点型转换成整型 i = 0x5fe6ec85e7de30da - (i >> 1) //0x5f3759df,注意这一行,另一个数字是0x5f375a86 y = math.Float64frombits(i) //内存不变,浮点型转换成整型 y = y * (f - (x * y * y)) y = y * (f - (x * y * y)) return number * y } //64位平方根倒数速算法2 func InvSqrt64(x1 float64) float64 { x := x1 xhalf := 0.5 * x i := math.Float64bits(xhalf) // get bits for floating VALUE i = 0x5fe6ec85e7de30da - (i >> 1) // gives initial guess y0 x = math.Float64frombits(i) // convert bits BACK to float x = x * (1.5 - xhalf*x*x) // Newton step, repeating increases accuracy x = x * (1.5 - xhalf*x*x) // Newton step, repeating increases accuracy x = x * (1.5 - xhalf*x*x) // Newton step, repeating increases accuracy return 1 / x } |
敲命令 go test -v -test.run TestSqrt后,结果如下:
公众号:福大大架构师每日一题
分类:
福大大架构师每日一题
标签:
算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具