小数点保留的计算方式与性能
案例
- 计算π保留15位小数
- 三种计算方式代码
//第1种 result := math.Round(pi*1e15) / 1e15 //第2种 result, _ := strconv.ParseFloat(strconv.FormatFloat(pi, 'f', 15, 64), 64) //第3种 result,_ := strconv.ParseFloat(fmt.Sprintf("%.15f", pi), 64)
结论
-
循环计算1千万次,第一种方法耗时最少
-
耗时表
方法 耗时 第1种 6 第2种 4650 第3种 5708
引申问题
- 会不会超过int64的大数导致计算溢出
maxint64值为9223372036854775807
使用值922337203685477580.1234567890
进行计算结果正确 - 为什么结果争取
在go内部使用IEEE-754标准
方式存储小数。不在此处详细介绍,大家可自行搜索
性能测试机器信息
- 2014年老mac笔记本
性能测试方法
- 代码
//TestDecimalPlacesPerformance 小数保留性能测试 func TestDecimalPlacesPerformance(t *testing.T) { max := 922337203685477580.1234567890 fmt.Printf("%v\n", max*11 ) pi := math.Pi //第1种方式功能测试 b1 := math.Round(pi*1e15) / 1e15 fmt.Printf("结果1 :%v\n", b1) //第2种方式功能测试 b2, _ := strconv.ParseFloat(strconv.FormatFloat(pi, 'f', 15, 64), 64) fmt.Printf("结果2 :%v\n", b2) //第3种方式功能测试 b3, _ := strconv.ParseFloat(fmt.Sprintf("%.15f", pi), 64) fmt.Printf("结果3 :%v\n", b3) fmt.Printf("----------------------------------------------------------------------\n") //循环次数 testTimes := int(1e7) //第1种方式耗时 startTime := time.Now().UnixNano() / 1e6 for i := 0; i < testTimes; i++ { _ = math.Round(pi*1e15) / 1e15 } fmt.Printf("耗时1 :%v\n", time.Now().UnixNano()/1e6-startTime) //第2种方式耗时 startTime = time.Now().UnixNano() / 1e6 for i := 0; i < testTimes; i++ { _, _ = strconv.ParseFloat(strconv.FormatFloat(pi, 'f', 15, 64), 64) } fmt.Printf("耗时2 :%v\n", time.Now().UnixNano()/1e6-startTime) //第3种方式耗时 startTime = time.Now().UnixNano() / 1e6 for i := 0; i < testTimes; i++ { _,_ = strconv.ParseFloat(fmt.Sprintf("%.15f", pi), 64) } fmt.Printf("耗时3 :%v\n", time.Now().UnixNano()/1e6-startTime) }