欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺析Golang中float64的精度問(wèn)題

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

現(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)了精度問(wèn)題
   xAdded2 := x + 2
   fmt.Println("2^53 + 2 =", xAdded2)                   // 9007199254740994
   fmt.Println("float64(2^53 + 2) =", float64(xAdded2)) // 9.007199254740994e+15,沒(méi)有出現(xiàn)精度問(wèn)題
   fmt.Println("math.MaxInt64 =", int64(math.MaxInt64))
   fmt.Println("float64(math.MaxInt64) =", float64(math.MaxInt64)) // 精度問(wèn)題
   fmt.Println("math.MaxUint64 =", uint64(math.MaxUint64))
}

運(yùn)行結(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無(wú)法精確存儲(chǔ)2^53 + 1,但能精確存儲(chǔ)2^53 + 2,為什么?

首先,float64的尾數(shù)位有52位,尾數(shù)的最大長(zhǎng)度只能是52+1=53位,尾數(shù)長(zhǎng)度超過(guò)53就無(wú)法精確存儲(chǔ),會(huì)存在精度問(wèn)題。

無(wú)法精確存儲(chǔ)2^53+1

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

能精確存儲(chǔ)2^53+2

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

知識(shí)補(bǔ)充

計(jì)算機(jī)的浮點(diǎn)數(shù)表示

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

在計(jì)算機(jī)中,是用二進(jìn)制的科學(xué)計(jì)數(shù)法來(lái)表示和存儲(chǔ)浮點(diǎn)數(shù)的。因?yàn)榭茖W(xué)計(jì)數(shù)法可以唯一地表示任何一個(gè)數(shù),且所占用的存儲(chǔ)空間會(huì)更少。

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

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

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

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

  • 對(duì)于單精度浮點(diǎn)數(shù),1位符號(hào)位+8位階碼位+23位尾數(shù)位。
  • 對(duì)于雙精度浮點(diǎn)數(shù),1位符號(hào)位+11位階碼位+52位尾數(shù)位。

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

比如,對(duì)于單精度浮點(diǎn)數(shù)(8位階碼位),無(wú)符號(hào)數(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ī)格化?保證浮點(diǎn)數(shù)有唯一的表示。若不對(duì)浮點(diǎn)數(shù)的表示作出明確規(guī)定,同一個(gè)浮點(diǎn)數(shù)的表示就不是唯一的,比如對(duì)于十進(jìn)制數(shù)1.75表示可能有1.11*2^0、0.111*2^1、0.0111*2^2等。

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

示例

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

  • 1.5
  • -12.5

對(duì)于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位符號(hào)位、8位階碼位和23位尾數(shù)位進(jìn)行編碼:

  • 因?yàn)槭钦龜?shù),所以單精度浮點(diǎn)數(shù)的1位符號(hào)位為0
  • 尾數(shù)是1.1,尾數(shù)位只需存儲(chǔ)1.1之后的1,因此單精度浮點(diǎn)數(shù)的23位尾數(shù)位就是10000000000000000000000
  • 階碼E=0,則e=E+127=127,因此階碼位對(duì)應(yīng)的無(wú)符號(hào)數(shù)e是127,所以單精度浮點(diǎn)數(shù)的8位階碼位是01111111

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

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

  • 因?yàn)槭秦?fù)數(shù),所以符號(hào)位是1
  • 尾數(shù)是1.1001,尾數(shù)位只需存儲(chǔ)1.1001之后的1001,所以尾數(shù)位是10010000000000000000000
  • 階碼E=3,則e=E+127=130,因此階碼位對(duì)應(yīng)的無(wú)符號(hào)數(shù)e是130,則階碼位是10000010

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

精度問(wèn)題

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

  • 對(duì)于單精度浮點(diǎn)數(shù),若尾數(shù)的長(zhǎng)度超過(guò)24位,24位之后的數(shù)字就無(wú)法存儲(chǔ),會(huì)出現(xiàn)精度問(wèn)題
  • 對(duì)于雙精度浮點(diǎn)數(shù),若尾數(shù)的長(zhǎng)度超過(guò)53位,53位之后的數(shù)字就無(wú)法存儲(chǔ),會(huì)出現(xiàn)精度問(wèn)題

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

相關(guān)文章

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

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

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

    golang端口占用檢測(cè)的使用

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

    Golang中的閉包(Closures)詳解

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

    使用go實(shí)現(xiàn)一個(gè)超級(jí)mini的消息隊(duì)列的示例代碼

    本文主要介紹了使用go實(shí)現(xiàn)一個(gè)超級(jí)mini的消息隊(duì)列的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    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語(yǔ)言高效編程的3個(gè)技巧總結(jié)

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

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

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

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

    Golang 空map和未初始化map的注意事項(xiàng)說(shuō)明

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

    Go項(xiàng)目分層下的最佳error處理方式分享

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

    完美解決golang go get私有倉(cāng)庫(kù)的問(wèn)題

    這篇文章主要介紹了完美解決golang go get私有倉(cāng)庫(kù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05

最新評(píng)論