day 24 - 失控的浮点数, decimal套件介绍

在写程序的过程, 多多少少会遇到需要复杂处理的状况, Go的优点是很多使用情境已经有前人帮忙整理成套件了, 只要go get 下来就可以马上使用, 这实在是省下了不少时间。其中一个就是浮点数处理。
Go的浮点数使用的是IEEE-754标准储存浮点数, wiki有详细的介绍, 主要是因为IEEE-754是采用二进位的方式运算, 在运算的过程当中会产生一个无限循环数, 经过四舍五入之後就出现了偏差值。这个坑很容易就会踩进去了, 算是写Go的过程多数人都会体验一回的坑。
为了修正这个浮点数问题, 在浮点数计算时我们会使用套件shopspring/decimal

先来看一下为处理前的状况, 数学计算时
0.3+0.6=0.9,

但是Go程序跑起来却不是这样, Go里面针对浮点数的部分有float32float64, 来跑跑看结果

  func main() {
      var (
          b1 float32
          b2 float32
          c1 float64
          c2 float64
      )

      b1 = 0.3
      c1 = 0.3
      b2 = 0.6
      c2 = 0.6

      b := b1 + b2
      fmt.Println("b:", b)

      c := c1 + c2
      fmt.Println("c:", c)

  }

结果

  b: 0.90000004
  c: 0.8999999999999999

是不是让人怀疑人生...../images/emoticon/emoticon19.gif

这时候把问题丢给Google, Google就会跳出前人的经验, 找到推荐的浮点数处理套件之後, 再来跑一次

  func main() {
      var (
          b1 float32
          b2 float32
          c1 float64
          c2 float64
      )

      b1 = 0.3
      c1 = 0.3
      b2 = 0.6
      c2 = 0.6

      b := b1 + b2
      fmt.Println("b:", b)

      bb, _ := decimal.NewFromFloat32(b1).Add(decimal.NewFromFloat32(b2)).Value()
      fmt.Println("bb:", bb)

      c := c1 + c2
      fmt.Println("c:", c)

      cc, _ := decimal.NewFromFloat(c1).Add(decimal.NewFromFloat(c2)).Float64()
      fmt.Println("cc:", cc)
  }

可以看到使用套件的运算结果有符合预期的状况。

  b: 0.90000004
  bb: 0.9
  c: 0.8999999999999999
  cc: 0.9

参考资料


<<:  [DAY18]旋转木马(01)

>>:  [13th][Day24] kubernetes 是什麽

Progressive Web App 推播协定 (26)

之前已经可以用後端的套件去实作推播的服务器,但那个套件实际上做了哪些事情? 金钥对 Applicat...

Day5 Python 基础教学 (四)

了解完型别之後,接下来就是该知道一些基础的语法了, 循环语法 range() 方法 在开始介绍Pyt...

[DAY14]Label进阶使用-Affinity and anti-affinity

把pod部署到特定node上面 k8s的特性来说,基本上部署到k8s一定是会挑资源最轻的那台node...

[D19] placeholder for d11

写在前面 placeholder for d11 placeholder for d11 place...

The Effective CISSP考试攻略

考试的难易 一个好的考试,通常会让你准备的很辛苦!但通过考试後会让你一直駡,怎麽考出来的题目没有想像...