亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺析Golang中float64的精度問題

 更新時間:2023年08月08日 11:47:40   作者:X_PENG  
這篇文章主要來和大家一起探討一下Golang中關(guān)于float64的精度問題,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解下

現(xiàn)象

func main() {
   x := uint64(1)
   for i := 0; i < 53; i++ {
      x = x * 2
   }
   fmt.Println("2^53 =", x)
   xStr := strconv.FormatUint(x, 10)
   fmt.Println("len(2^53) =", len(xStr))
   xAdded1 := x + 1
   fmt.Println("2^53 + 1 =", xAdded1)                   // 9007199254740993
   fmt.Println("float64(2^53 + 1) =", float64(xAdded1)) // 9.007199254740992e+15,出現(xiàn)了精度問題
   xAdded2 := x + 2
   fmt.Println("2^53 + 2 =", xAdded2)                   // 9007199254740994
   fmt.Println("float64(2^53 + 2) =", float64(xAdded2)) // 9.007199254740994e+15,沒有出現(xiàn)精度問題
   fmt.Println("math.MaxInt64 =", int64(math.MaxInt64))
   fmt.Println("float64(math.MaxInt64) =", float64(math.MaxInt64)) // 精度問題
   fmt.Println("math.MaxUint64 =", uint64(math.MaxUint64))
}

運行結(jié)果:

2^53 = 9007199254740992
len(2^53) = 16
2^53 + 1 = 9007199254740993
float64(2^53 + 1) = 9.007199254740992e+15
2^53 + 2 = 9007199254740994
float64(2^53 + 2) = 9.007199254740994e+15
math.MaxInt64 = 9223372036854775807
float64(math.MaxInt64) = 9.223372036854776e+18
math.MaxUint64 = 18446744073709551615

分析

可以看到float64無法精確存儲2^53 + 1,但能精確存儲2^53 + 2,為什么?

首先,float64的尾數(shù)位有52位,尾數(shù)的最大長度只能是52+1=53位,尾數(shù)長度超過53就無法精確存儲,會存在精度問題。

無法精確存儲2^53+1

2^53+1的二進(jìn)制是10000000....0001(中間有52個0),根據(jù)IEEE標(biāo)準(zhǔn)則是(-1)^0 * 1.000000000...01(中間有52個0) * 2^53,尾數(shù)長度是54,超過了53,因此float64無法存儲第54位,只能舍去最后的1,所以存在精度問題。

能精確存儲2^53+2

2^53+2的二進(jìn)制是1000000...010(中間51個0),根據(jù)IEEE標(biāo)準(zhǔn)則是(-1)^0 * 1.00000000...01(中間是51個0)* 2^53,尾數(shù)長度是53,float64的尾數(shù)位可以精確存儲,因此沒有精度問題。

知識補充

計算機的浮點數(shù)表示

科學(xué)計數(shù)法和IEEE標(biāo)準(zhǔn)

在計算機中,是用二進(jìn)制的科學(xué)計數(shù)法來表示和存儲浮點數(shù)的。因為科學(xué)計數(shù)法可以唯一地表示任何一個數(shù),且所占用的存儲空間會更少。

比如:對于一個二進(jìn)制數(shù)100000...000(共127個0),如果不用科學(xué)計數(shù)法,需要16個字節(jié)來存儲。如果用科學(xué)計數(shù)法:1*2^127,只需要用二進(jìn)制表示出:有效數(shù)字和指數(shù)即可,壓根不需要16個字節(jié)。

IEEE浮點標(biāo)準(zhǔn)用V=(-1)^s * M * 2^E的形式來表示一個數(shù):

  • 符號:s決定該數(shù)是正數(shù)還是負(fù)數(shù)(0正1負(fù)),而對于數(shù)值0的符號位解釋作為特殊情況處理。
  • 尾數(shù)(相當(dāng)于有效數(shù)字):M是一個二進(jìn)制小數(shù),對于規(guī)格化表示:1<=M<2
  • 階碼(相當(dāng)于指數(shù)):階碼E決定了二進(jìn)制小數(shù)的小數(shù)點位置。(可為負(fù)數(shù))

將一個浮點數(shù)的表示轉(zhuǎn)成如上形式,然后分別對符號、尾數(shù)和階碼進(jìn)行編碼就能得到浮點數(shù)的機器表示。
如下,IEEE標(biāo)準(zhǔn)規(guī)定:

  • 對于單精度浮點數(shù),1位符號位+8位階碼位+23位尾數(shù)位。
  • 對于雙精度浮點數(shù),1位符號位+11位階碼位+52位尾數(shù)位。

IEEE標(biāo)準(zhǔn)規(guī)定:階碼位表示的是無符號數(shù)e,階碼E無符號數(shù)e的關(guān)系是:E = e - (2^(n-1) - 1)。

比如,對于單精度浮點數(shù)(8位階碼位),無符號數(shù)e的范圍是[0, 255],因此E = e - (2^7 - 1) = e - 127,所以階碼E的范圍是[-127, 128],即指數(shù)的范圍是[-127, 128]。

尾數(shù)的規(guī)格化表示: 尾數(shù)M必須1<=M<2。

為什么要規(guī)格化?保證浮點數(shù)有唯一的表示。若不對浮點數(shù)的表示作出明確規(guī)定,同一個浮點數(shù)的表示就不是唯一的,比如對于十進(jìn)制數(shù)1.75表示可能有1.11*2^0、0.111*2^1、0.0111*2^2等。

規(guī)格化表示后,尾數(shù)一定是1.xxxx,由于第一位一定是1,所以不需要顯式地表示它,因此尾數(shù)位全部用來表示尾數(shù)1.xxxx之后的xxxx部分,也就是說【尾數(shù)的長度(去除小數(shù)點)】最多是【尾數(shù)位+1位】,尾數(shù)超過這個長度之后的數(shù)字位都會被舍棄,從而出現(xiàn)精度問題。

示例

將如下十進(jìn)制數(shù)轉(zhuǎn)成單精度浮點數(shù)表示:

  • 1.5
  • -12.5

對于1.5,其二進(jìn)制小數(shù)是1.1,按照IEEE標(biāo)準(zhǔn)轉(zhuǎn)成V=(-1)^s * M * 2^E的形式,即(-1)^0 * 1.1 * 2^0,所以:s=0;M=1.1;E=0。然后分別用1位符號位、8位階碼位和23位尾數(shù)位進(jìn)行編碼:

  • 因為是正數(shù),所以單精度浮點數(shù)的1位符號位為0
  • 尾數(shù)是1.1,尾數(shù)位只需存儲1.1之后的1,因此單精度浮點數(shù)的23位尾數(shù)位就是10000000000000000000000
  • 階碼E=0,則e=E+127=127,因此階碼位對應(yīng)的無符號數(shù)e是127,所以單精度浮點數(shù)的8位階碼位是01111111

最終,二進(jìn)制表示為00111111110000000000000000000000

同理,對于-12.5,其二進(jìn)制小數(shù)是-1100.1,即(-1)^1 * 1.1001 * 2^3,所以:s=0;M=1.1001;E=3。然后分別用1位符號位、8位階碼位和23位尾數(shù)位進(jìn)行編碼:

  • 因為是負(fù)數(shù),所以符號位是1
  • 尾數(shù)是1.1001,尾數(shù)位只需存儲1.1001之后的1001,所以尾數(shù)位是10010000000000000000000
  • 階碼E=3,則e=E+127=130,因此階碼位對應(yīng)的無符號數(shù)e是130,則階碼位是10000010

最終,二進(jìn)制表示為11000001010010000000000000000000

精度問題

單精度浮點數(shù)有23位尾數(shù)位,最多只能表示23+1=24位長度的尾數(shù);雙精度浮點數(shù)有52位尾數(shù)位,最多只能表示52+1=53位長度的尾數(shù)。 也就是說:

  • 對于單精度浮點數(shù),若尾數(shù)的長度超過24位,24位之后的數(shù)字就無法存儲,會出現(xiàn)精度問題
  • 對于雙精度浮點數(shù),若尾數(shù)的長度超過53位,53位之后的數(shù)字就無法存儲,會出現(xiàn)精度問題

到此這篇關(guān)于淺析Golang中float64的精度問題的文章就介紹到這了,更多相關(guān)Go float64精度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言使用templ實現(xiàn)編寫HTML用戶界面

    Go語言使用templ實現(xiàn)編寫HTML用戶界面

    templ是一個在 Go 中編寫 HTML 用戶界面的語言,使用 templ,我們可以創(chuàng)建可呈現(xiàn) HTML 片段的組件,下面就跟隨小編一起了解一下具體的實現(xiàn)方法吧
    2023-12-12
  • golang端口占用檢測的使用

    golang端口占用檢測的使用

    這篇文章主要介紹了golang端口占用檢測的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Golang中的閉包(Closures)詳解

    Golang中的閉包(Closures)詳解

    在?Golang?中,閉包是一個引用了作用域之外的變量的函數(shù),Golang?中的匿名函數(shù)也被稱為閉包,閉包可以被認(rèn)為是一種特殊類型的匿名函數(shù),所以本文就給大家詳細(xì)的介紹一下Golang的閉包到底是什么,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07
  • 使用go實現(xiàn)一個超級mini的消息隊列的示例代碼

    使用go實現(xiàn)一個超級mini的消息隊列的示例代碼

    本文主要介紹了使用go實現(xiàn)一個超級mini的消息隊列的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 在Visual Studio Code中配置GO開發(fā)環(huán)境的詳細(xì)教程

    在Visual Studio Code中配置GO開發(fā)環(huán)境的詳細(xì)教程

    這篇文章主要介紹了在Visual Studio Code中配置GO開發(fā)環(huán)境的詳細(xì)教程,需要的朋友可以參考下
    2017-02-02
  • Go語言高效編程的3個技巧總結(jié)

    Go語言高效編程的3個技巧總結(jié)

    Go語言是一種開源編程語言,可輕松構(gòu)建簡單、可靠且高效的軟件,下面這篇文章主要給大家分享介紹了關(guān)于Go語言高效編程的3個技巧,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • 詳解Golang如何優(yōu)雅判斷interface是否為nil

    詳解Golang如何優(yōu)雅判斷interface是否為nil

    這篇文章主要為大家詳細(xì)介紹了Golang如何優(yōu)雅判斷interface是否為nil的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解下
    2024-01-01
  • Golang 空map和未初始化map的注意事項說明

    Golang 空map和未初始化map的注意事項說明

    這篇文章主要介紹了Golang 空map和未初始化map的注意事項說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go項目分層下的最佳error處理方式分享

    Go項目分層下的最佳error處理方式分享

    這篇文章主要來和大家一起探討?Go?項目分層下的最佳?error?處理方式,準(zhǔn)備好了嗎?準(zhǔn)備一杯你最喜歡的飲料或茶,隨著本文一探究竟吧
    2023-06-06
  • 完美解決golang go get私有倉庫的問題

    完美解決golang go get私有倉庫的問題

    這篇文章主要介紹了完美解決golang go get私有倉庫的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05

最新評論