亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

謹慎使用單精度/雙精度這兩數值類型

2019-11-18 11:58:20
字體:
來源:轉載
供稿:網友

  前言
  
  在近日幾個帖子里面,和QQ群的討論里面,我發現很多網友都碰到的問題都是因為不恰當地使用了單精度/雙精度數值。因此想專門就這個話題談一下。
  
  單精度和雙精度數值類型最早出現在C語言中(比較通用的語言里面),在C語言中單精度類型稱為浮點類型(Float),顧名思義是通過浮動小數點來實現數據的存儲。這兩個數據類型最早是為了科學計算而產生的,他能夠給科學計算提供足夠高的精度來存儲對于精度要求比較高的數值。但是與此同時,他也完全符合科學計算中對于數值的觀念:
  
  當我們比較兩個棍子的長度的時候,一種方法是并排放著比較一下,一種方法是分別量出長度。但是事實上世界上并不存在兩根完全一樣長的棍子,我們測量的長度精度受到人類目測能力和測量工具精度的限制。從這個意義上來說,判定兩根棍子是否一樣長絲毫沒有意義,因為結果一定是False,但是我們可以比較他們兩個哪個更長或者更短。這個例子很好地概括了單精度/雙精度數值類型的設計初衷和存在意義。
  
  基于上述熟悉,單精度/雙精度數值類型從一開始設計的時候,就不是一個準確的數值類型,他只保證在他這個數值類型的精度之內是準確的,精度之外則不保證,比方說,一個數值5.1,很可能存儲在單精度/雙精度數值中的實際值是5.100000000001或者5.09999999999999。導致這個現象的原因我們可以通過兩種方式來解釋:
  
  簡單的解釋方法:
  
  你可以嘗試在任何一個控件的屬性面板中,設定他的寬度為:3.2CM,當你輸入完畢后,你會發現值自動變成了3.199cm,無論你怎么改,你都無法輸入3.200CM,因為實際上在電腦中存儲的并不是CM為單位的數值,而是“緹”為單位的數值,而“緹”和CM之間的比值,是個很難被除盡的數,因此你輸入完畢后,電腦自動轉換成了最接近的“緹”值,然后再轉換成厘米顯示到屬性面板上,這一乘一除,兩次四舍五入,誤差就出來了。單精度/雙精度也是類似的原理,其實在二進制存儲的時候,單精度/雙精度都采用了類似相近分數的方法,而這樣的存儲是不可能做到準確的。
  
  深入的解釋方法:
  
  讓我們來看看我們存儲到數字介質中的單精度/雙精度值到底是怎么樣的,我們使用如下代碼對單精度類型進行一個解剖:
  
  Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
  
  Public Sub floatTest()
  Dim dblVar As Single
  
  dblVar = 5.731 / 8
  dblOutput dblVar
  
  dblVar = dblVar * 2
  dblOutput dblVar
  
  dblVar = dblVar * 2
  dblOutput dblVar
  
  dblVar = dblVar * 2
  dblOutput dblVar
  
  dblVar = dblVar * 2
  dblOutput dblVar
  
  dblVar = dblVar * 2
  dblOutput dblVar
  
  End Sub
  
  Public Sub dblOutput(ByVal dblVar As Single)
  Dim bytVar(3) As Byte
  Dim i As Integer, j As Integer
  Dim strVar As String
  
  CopyMemory ByVal VarPtr(bytVar(0)), ByVal VarPtr(dblVar), 4
  strVar = dblVar & ": "
  For i = 3 To 0 Step -1
  For j = 7 To 0 Step -1
  strVar = strVar & (bytVar(i) And 2 ^ j) / 2 ^ j
  Next j
  strVar = strVar & " "
  Next i
  Debug.PRint strVar
  
  End Sub
  運行后我們得到輸出結果(輸出格式為高位左,低位右):
  
  .716375: 00111111 00110111 01100100 01011010
  1.43275: 00111111 10110111 01100100 01011010
  2.8655: 01000000 00110111 01100100 01011010
  5.731: 01000000 10110111 01100100 01011010
  11.462: 01000001 00110111 01100100 01011010
  22.924: 01000001 10110111 01100100 01011010
  
  這里,我們把單精度類型轉化成了二進制數據輸出,這里我們看到,雖然這六個數字完全不同,但是他們的二進制存儲驚人地相似,我們看到紅色標記部分,每次都是加1,事實上,單精度數據類型使用從高位開始第1位作為正負標記位(綠色),第2位到第9位,是一個跨字節的有符號字節類型數據,這個數值決定了小數點移動的方向和位數(紅色),第10位到32位保存一個整數(藍色)在存儲過程中,電腦首先把輸入的值不斷移位(乘除2)直到這個數的整數部分占用了全部24位的整數位,然后把移動的位數寫入浮點部分(紅色),而移位后的結果寫入整數部分(藍色和綠色),小數部分則舍棄。求值的時候則是反向過程,先根據正負位和整數位求值,然后根據紅色部分的整數來進行移位(乘除2的次方),最終才是我們得到的單精度數值。雙精度數值也是同樣原理,只是位數更多而已。
  
  通過解剖單精度數值的二進制存儲格式,我們可以清楚看到,實際上單精度/雙精度的存儲,都要通過乘法和除法,其中必有舍入,假如恰好你的數值在除法中被舍入了,那么你賦的初值就很可能與你最終存儲的值不完全相同,其中的微小差異,并不與單精度/雙精度的設計目標相違反。
  
  當我們在數據庫中或者VBA代碼中使用一個單精度/雙精度數值的時候,也許你從界面上看不到區別,但是在實際的存儲中,這個差別卻真真切切地就在那里,當你對其進行相等比較的時候,系統只是簡單地作二進制的比較,界面上無法體現的微小差異,在二進制比較面前卻無處遁形,于是,你的等于比較返回了一個意料之外的False。
  
  結束語
  
  通過本文,我們介紹了單精度/雙精度數據類型的實質以及其特點(優點和缺點),通過比較和解剖我們了解到單精度/雙精度實際上存儲的是一個近似值,浮點的特性決定了他可以存儲非常小的數,也可以存儲極大的數,他的數據精度并不是一個絕對值,而是存儲值的百分比,假如你存儲10的100次方,誤差就可能是10的80次方,假如你存儲10的-100次方,誤差就可能是10的-120次方。因此單精度/雙精度數據類型不能進行相等的比較(或數據庫關聯)。
  
  假如你需要進行等值比較或關聯,那么有以下幾種方案:
  
  1、使用專為準確度而設計的貨幣類型。
  
  2、使用整數類型存儲,代碼中移位。
  
  3、某些特定情況下可以用文字存儲。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97在线视频免费观看| 青青久久av北条麻妃海外网| 亚洲奶大毛多的老太婆| 成人h片在线播放免费网站| 成人免费福利视频| 日韩a**站在线观看| 日韩经典中文字幕在线观看| 国产精品久久一区| 亚洲人午夜色婷婷| 粉嫩老牛aⅴ一区二区三区| 国产精品电影网| 亚洲福利视频二区| 国产在线视频不卡| 久久久精品久久久久| 国产精品入口免费视| 欧美乱人伦中文字幕在线| 国产日本欧美一区二区三区| 欧美精品久久久久久久免费观看| 有码中文亚洲精品| 自拍亚洲一区欧美另类| 神马久久久久久| 国产99久久精品一区二区永久免费| 在线看欧美日韩| 91精品久久久久久久久青青| 精品视频偷偷看在线观看| 亚洲天堂男人的天堂| 国产成人免费av| 久久久国产精彩视频美女艺术照福利| 欧美在线视频一二三| 欧美色另类天堂2015| 国产啪精品视频网站| 91精品国产自产在线| 最近2019中文字幕大全第二页| 国产一区二区三区在线视频| 亚洲一区二区精品| 国色天香2019中文字幕在线观看| 国产成人97精品免费看片| 欧美在线一区二区视频| 久久99久久99精品中文字幕| 欧美高清视频在线| 高清在线视频日韩欧美| 精品久久久久久久中文字幕| www.日韩.com| 亚洲美腿欧美激情另类| 欧美日韩国产综合新一区| 午夜剧场成人观在线视频免费观看| 欧美性生交大片免网| 亚洲精品www久久久| 国产精品一区二区久久精品| 精品国产91乱高清在线观看| 国产欧美久久久久久| 欧美成人久久久| 97视频在线观看免费高清完整版在线观看| 久久的精品视频| 亚洲小视频在线观看| 久久久91精品国产一区不卡| 亚洲国产精品久久精品怡红院| 亚洲福利小视频| 日韩av片免费在线观看| 精品成人69xx.xyz| 97久久伊人激情网| 国产欧美精品久久久| 91精品国产高清久久久久久久久| 97香蕉久久超级碰碰高清版| 在线观看国产精品91| 欧美成人精品一区| 国产精品网站大全| 精品magnet| 日韩精品极品在线观看播放免费视频| 欧美老女人bb| 亚洲性生活视频在线观看| 亚洲精品99999| 38少妇精品导航| 久久久久国产一区二区三区| 国产婷婷97碰碰久久人人蜜臀| 中文字幕9999| 在线观看国产成人av片| 欧美日韩黄色大片| 欧美精品一本久久男人的天堂| 97视频国产在线| 国语自产在线不卡| 久久久久九九九九| 日韩av在线网址| 中文字幕精品av| 亚洲理论在线a中文字幕| 51精品国产黑色丝袜高跟鞋| 欧美激情综合色综合啪啪五月| 欧美亚洲免费电影| 久久久久九九九九| 欧洲亚洲女同hd| 久久躁日日躁aaaaxxxx| 亚洲色图17p| 亚洲国内高清视频| 久久久久久伊人| 国产成人一区二区三区电影| 日韩电视剧在线观看免费网站| 久久香蕉国产线看观看av| 国产mv久久久| 亚洲男人av电影| 国产精品高潮呻吟久久av无限| 亚洲高清一区二| 中文字幕av日韩| 黑人巨大精品欧美一区免费视频| 91av免费观看91av精品在线| 亚洲人成在线一二| 久久久久久国产精品| 91精品国产91久久| 亚洲激情成人网| 国产亚洲精品一区二555| 亚洲大胆人体在线| 欧美一区第一页| 琪琪第一精品导航| 尤物九九久久国产精品的分类| 国产成人精品综合| 狠狠爱在线视频一区| 97精品国产97久久久久久免费| 日韩美女av在线免费观看| 欧美亚洲伦理www| 精品无人区太爽高潮在线播放| 欧美大学生性色视频| 夜夜狂射影院欧美极品| 米奇精品一区二区三区在线观看| 日韩亚洲一区二区| 精品久久久久久| 亚洲欧洲激情在线| 国产精品热视频| 亚洲精品综合久久中文字幕| 欧美日本黄视频| 中文在线资源观看视频网站免费不卡| 国产精品激情av电影在线观看| 亚洲欧美制服丝袜| 欧美日韩国产丝袜另类| 日韩中文字幕在线免费观看| 国产亚洲激情视频在线| 欧美日韩一区二区在线播放| 色狠狠av一区二区三区香蕉蜜桃| 宅男66日本亚洲欧美视频| 日韩一级黄色av| 一区二区三区国产在线观看| 国产精品视频xxx| 精品久久久久久国产| 日韩国产精品一区| 国产精品亚洲一区二区三区| 久久久久久久久久av| 91情侣偷在线精品国产| 尤物精品国产第一福利三区| 日韩在线资源网| 国产精品久久久久久影视| 97久久精品在线| 亚洲国产一区二区三区四区| 亚洲国产精品嫩草影院久久| 久久久久久久久久国产| 欧美黑人极品猛少妇色xxxxx| 欧美精品videossex性护士| 欧美特级www| 午夜精品国产精品大乳美女| 91精品国产乱码久久久久久蜜臀| 96pao国产成视频永久免费| 国产原创欧美精品| 欧美另类99xxxxx| 欧美激情网站在线观看| 久久久精品视频在线观看| 欧美午夜精品久久久久久人妖| 91成人在线观看国产|