单精度和双精度? 单精度和双精度有什么不同?

\u4ec0\u4e48\u662f\u5355\u7cbe\u5ea6\u548c\u53cc\u7cbe\u5ea6?

\u6240\u8c13\u7684\u7cbe\u5ea6\u5728c#\u8868\u793a\u6d6e\u70b9\u7c7b\u578b\uff08\u4e5f\u5c31\u662f\u5e26\u5c0f\u6570\u70b9\u7684\uff09
\u5355\u7cbe\u5ea6\u7684\u6570\u636e\u7c7b\u578b\u662ffloat
\u53cc\u7cbe\u5ea6\u7684\u6570\u636e\u7c7b\u578b\u662fdouble
\u5355\u7cbe\u5ea6\u4e0e\u53cc\u7cbe\u5ea6\u7684\u533a\u522b\u662f\u5355\u7cbe\u5ea6\u7684\u53d6\u503c\u8303\u56f4\u6ca1\u6709\u53cc\u7cbe\u5ea6\u7684\u5927
\u7f16\u8bd1\u5668\u9ed8\u8ba4\u7684\u6d6e\u70b9\u7c7b\u578b\u662f\u53cc\u7cbe\u5ea6

\u5355\u7cbe\u5ea6\u6d6e\u70b9\u6570\u548c\u53cc\u7cbe\u5ea6\u6d6e\u70b9\u6570\u6709\u4ee5\u4e0b\u533a\u522b\uff1a
1\u3001\u6240\u5360\u7684\u5185\u5b58\u4e0d\u540c
\u5355\u7cbe\u5ea6\u6d6e\u70b9\u6570\u5360\u75284\u4e2a\u5b57\u8282\uff0832\u4f4d\uff09\u5b58\u50a8\u7a7a\u95f4\u6765\u5b58\u50a8\u4e00\u4e2a\u6d6e\u70b9\u6570\uff0c\u5305\u62ec\u7b26\u53f7\u4f4d1\u4f4d\uff0c\u9636\u78018\u4f4d\uff0c\u5c3e\u657023\u4f4d\u3002
\u800c\u53cc\u7cbe\u5ea6\u6d6e\u70b9\u6570\u4f7f\u7528 8\u4e2a\u5b57\u8282\uff0864\u4f4d\uff09\u5b58\u50a8\u7a7a\u95f4\u6765\u5b58\u50a8\u4e00\u4e2a\u6d6e\u70b9\u6570\uff0c\u5305\u62ec\u7b26\u53f7\u4f4d1\u4f4d\uff0c\u9636\u780111\u4f4d\uff0c\u5c3e\u657052\u4f4d\u3002
2\u3001\u6240\u5b58\u7684\u6570\u503c\u8303\u56f4\u4e0d\u540c
\u5355\u7cbe\u5ea6\u6d6e\u70b9\u6570\u7684\u6570\u503c\u8303\u56f4\u4e3a-3.4E38\uff5e3.4E38\uff0c\u800c\u53cc\u7cbe\u5ea6\u6d6e\u70b9\u6570\u53ef\u4ee5\u8868\u793a\u7684\u6570\u5b57\u7684\u7edd\u5bf9\u503c\u8303\u56f4\u5927\u7ea6\u662f\uff1a-2.23E308 ~ 1.79E308\u3002E\u8868\u793a10\u7684\u591a\u5c11\u6b21\u65b9\uff0c\u59823.4E38\u6307\u7684\u662f3.4\u4e58\u4ee510\u768438\u6b21\u65b9\u3002
3\u3001\u5341\u8fdb\u5236\u4e0b\u7684\u4f4d\u6570\u4e0d\u540c
\u5355\u7cbe\u5ea6\u6d6e\u70b9\u6570\u6700\u591a\u67097\u4f4d\u5341\u8fdb\u5236\u6709\u6548\u6570\u5b57\uff0c\u5982\u679c\u67d0\u4e2a\u6570\u7684\u6709\u6548\u6570\u5b57\u4f4d\u6570\u8d85\u8fc77\u4f4d\uff0c\u5f53\u628a\u5b83\u5b9a\u4e49\u4e3a\u5355\u7cbe\u5ea6\u53d8\u91cf\u65f6\uff0c\u8d85\u51fa\u7684\u90e8\u5206\u4f1a\u81ea\u52a8\u56db\u820d\u4e94\u5165\u3002
\u53cc\u7cbe\u5ea6\u6d6e\u70b9\u6570\u53ef\u4ee5\u8868\u793a\u5341\u8fdb\u5236\u768415\u621616\u4f4d\u6709\u6548\u6570\u5b57\uff0c\u8d85\u51fa\u7684\u90e8\u5206\u4e5f\u4f1a\u81ea\u52a8\u56db\u820d\u4e94\u5165\u3002

\u53c2\u8003\u8d44\u6599\u6765\u6e90\uff1a\u767e\u5ea6\u767e\u79d1-\u5355\u7cbe\u5ea6\u6d6e\u70b9\u6570
\u53c2\u8003\u8d44\u6599\u6765\u6e90\uff1a\u767e\u5ea6\u767e\u79d1-\u53cc\u7cbe\u5ea6\u6d6e\u70b9\u6570

  单精度和双精度数值类型最早出现在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。

  • 鍗曠簿搴﹀拰鍙岀簿搴?
    绛旓細鍗曠簿搴﹀拰鍙岀簿搴︽槸娴偣鏁扮殑涓ょ涓嶅悓鐨勮〃绀烘柟娉銆傝В閲婂涓嬶細鍗曠簿搴︽诞鐐规暟鏄竴绉嶈绠楁満鏁版嵁绫诲瀷锛屽畠鐢ㄤ簬琛ㄧず甯︽湁灏忔暟鐐圭殑鏁板笺傚崟绮惧害娴偣鏁伴氬父鍗犵敤璁$畻鏈哄唴瀛樹腑鐨勫洓涓瓧鑺傦紝瀹冨彲浠ヨ〃绀虹殑鑼冨洿鐩稿杈冨皬锛岀簿搴︿篃鐩稿杈冧綆銆傜敱浜庡叾璁$畻鏁堢巼杈冮珮锛屾墍浠ュ湪涓浜涘绮惧害瑕佹眰涓嶆槸鐗瑰埆楂樼殑鍦哄悎涓紝閫氬父浼氫娇鐢ㄥ崟绮惧害娴偣鏁...
  • 鍗曠簿搴﹀拰鍙岀簿搴鏈変粈涔堜笉鍚?
    绛旓細鍗曠簿搴︽诞鐐规暟鍜屽弻绮惧害娴偣鏁版湁浠ヤ笅鍖哄埆锛1銆佹墍鍗犵殑鍐呭瓨涓嶅悓 鍗曠簿搴︽诞鐐规暟鍗犵敤4涓瓧鑺傦紙32浣嶏級瀛樺偍绌洪棿鏉ュ瓨鍌ㄤ竴涓诞鐐规暟锛屽寘鎷鍙蜂綅1浣嶏紝闃剁爜8浣嶏紝灏炬暟23浣嶃傝屽弻绮惧害娴偣鏁颁娇鐢 8涓瓧鑺傦紙64浣嶏級瀛樺偍绌洪棿鏉ュ瓨鍌ㄤ竴涓诞鐐规暟锛屽寘鎷鍙蜂綅1浣嶏紝闃剁爜11浣嶏紝灏炬暟52浣嶃2銆佹墍瀛樼殑鏁板艰寖鍥翠笉鍚 鍗曠簿搴︽诞鐐...
  • 浠涔堟槸鍗曠簿搴﹀拰鍙岀簿搴?
    绛旓細鍗曠簿搴鏁版槸鎸囪绠楁満琛ㄨ揪瀹炴暟杩戜技鍊肩殑涓绉嶆柟寮忋俈B涓璖ingle锛堝崟绮惧害娴偣鍨嬶級鍙橀噺瀛樺偍涓 IEEE 32 浣嶏紙4 涓瓧鑺傦級娴偣鏁板肩殑褰㈠紡锛屽畠鐨勮寖鍥村湪璐熸暟鐨勬椂鍊欐槸浠 -3.402823E38 鍒 -1.401298E-45锛岃屽湪姝f暟鐨勬椂鍊欐槸浠 1.401298E-45 鍒 3.402823E38 銆鍙岀簿搴娴偣鏁(double)鏄绠楁満浣跨敤鐨勪竴绉嶆暟鎹被鍨...
  • 浠涔堟槸鍗曠簿搴﹀拰鍙岀簿搴?
    绛旓細鍗曠簿搴︼細鍗曠簿搴︽暟鏄寚璁$畻鏈鸿〃杈惧疄鏁拌繎浼煎肩殑涓绉嶆柟寮銆俈B涓璖ingle锛堝崟绮惧害娴偣鍨嬶級鍙橀噺瀛樺偍涓篒EEE32浣嶏紙4涓瓧鑺傦級娴偣鏁板肩殑褰㈠紡锛屽畠鐨勮寖鍥村湪璐熸暟鐨勬椂鍊欐槸浠-3.402823E38鍒-1.401298E-45锛岃屽湪姝f暟鐨勬椂鍊欐槸浠1.401298E-45鍒3.402823E38銆傚弻绮惧害锛氬弻绮惧害娴偣鏁(double)鏄绠楁満浣跨敤鐨勪竴绉嶆暟鎹被鍨...
  • 鍗曠簿搴﹀拰鍙岀簿搴鏈変粈涔堝尯鍒?
    绛旓細涓銆佹寚浠d笉鍚 1銆佸崟绮惧害锛氭槸鎸囪绠楁満琛ㄨ揪瀹炴暟杩戜技鍊肩殑涓绉嶆柟寮忋2銆佸弻绮惧害锛氭鏁版嵁绫诲瀷涓庡崟绮惧害鏁版嵁绫诲瀷(float)鐩镐技锛屼絾绮剧‘搴︽瘮float楂樸備簩銆佽寖鍥翠笉鍚 1銆佸崟绮惧害锛氳寖鍥村湪璐熸暟鐨勬椂鍊欐槸浠 -3.402823E38 鍒 -1.401298E-45锛岃屽湪姝f暟鐨勬椂鍊欐槸浠 1.401298E-45 鍒 3.402823E38 銆2銆佸弻绮惧害锛氬弻...
  • 鍗曠簿搴﹀拰鍙岀簿搴鏈変粈涔堝尯鍒晩?
    绛旓細1銆鍗曠簿搴﹀拰鍙岀簿搴鐨勫瓧鑺傛暟涓嶅悓锛氬墠鑰呭崰4涓瓧鑺傦紱鍚庤呭崰8涓瓧鑺傘2銆佸崟绮惧害鍜屽弻绮惧害鏈夋晥鏁板瓧浣嶆暟涓嶅悓锛氬墠鑰呬负8浣嶏紱鍚庤呬负16浣嶃3銆佸崟绮惧害鍜屽弻绮惧害琛ㄧず鐨勬暟鐨勮寖鍥翠笉鍚岋細鍓嶈呯殑鏁板艰寖鍥村湪-3.40E+38 鍒 +3.40E+38涔嬮棿锛涘悗鑰呯殑鑼冨洿涓-1.79E+308鍒+1.79E+308涔嬮棿銆4銆佸崟绮惧害鍜屽弻绮惧害澶勭悊鐨...
  • 鍗曠簿搴﹀拰鍙岀簿搴鏈変粈涔堜笉鍚?
    绛旓細鍗曠簿搴﹀拰鍙岀簿搴瀛樺湪涓嶅悓鐨勭簿搴︽爣鍑嗐備竴銆鍗曠簿搴︿笌鍙岀簿搴瀹氫箟 鍦ㄨ绠楁満绉戝涓紝鍗曠簿搴﹀拰鍙岀簿搴︽槸鎸囨诞鐐规暟绫诲瀷鐨勪袱绉嶄笉鍚岀殑琛ㄧず鏂规硶銆傚畠浠殑涓昏鍖哄埆鍦ㄤ簬瀛樺偍鏁版嵁鏃舵墍閲囩敤鐨勭簿搴﹀拰瀛樺偍绌洪棿鐨勫ぇ灏忋傚崟绮惧害娴偣鏁伴氬父閲囩敤32浣嶄簩杩涘埗鏍煎紡锛屽寘鎷鍙蜂綅銆佹寚鏁颁綅鍜屽熬鏁颁綅銆傝屽弻绮惧害娴偣鏁板垯閲囩敤64浣嶄簩杩涘埗鏍煎紡锛...
  • 浠涔堟槸鍗曠簿搴﹀拰鍙岀簿搴?
    绛旓細鎵璋撶殑绮惧害鍦╟#琛ㄧず娴偣绫诲瀷锛堜篃灏辨槸甯﹀皬鏁扮偣鐨勶級鍗曠簿搴︾殑鏁版嵁绫诲瀷鏄痜loat鍙岀簿搴︾殑鏁版嵁绫诲瀷鏄痙ouble鍗曠簿搴︿笌鍙岀簿搴鐨勫尯鍒槸鍗曠簿搴︾殑鍙栧艰寖鍥存病鏈夊弻绮惧害鐨勫ぇ缂栬瘧鍣ㄩ粯璁ょ殑娴偣绫诲瀷鏄弻绮惧害
  • 鍗曠簿搴﹀拰鍙岀簿搴鏈変粈涔堜笉鍚?
    绛旓細1锛鍗曠簿搴娴偣鍨嬩负float锛 鍙岀簿搴娴偣鍨嬩负double銆2锛孎loat涓哄崟绮惧害锛屽唴瀛樹腑鍗4涓瓧鑺傦紝鏈夋晥鏁颁綅鏄7浣嶏紙鍥犱负鏈夋璐燂紝鎵浠ヤ笉鏄8浣嶏級锛屽湪鎴戠殑鐢佃剳涓擵C++6.0骞冲彴涓粯璁ゆ樉绀烘槸6浣嶆湁鏁堟暟瀛椼3锛宒ouble涓哄弻绮惧害锛屽崰8涓瓧鑺傦紝鏈夋晥鏁颁綅鏄16浣嶏紝浣嗗湪鎴戠殑鐢佃剳涓擵C++6.0骞冲彴涓粯璁ゆ樉绀哄悓鏍锋槸6浣嶆湁鏁堟暟瀛椼...
  • 鍗曠簿搴銆鍙岀簿搴鍚勬湁鍑犱綅灏忔暟?
    绛旓細鍗曠簿搴鏈6浣嶅皬鏁帮紝鍙岀簿搴鏈15浣嶅皬鏁般傚崟绮惧害鏁帮紙float鍨嬶級鍦32浣嶈绠楁満涓瓨鍌ㄥ崰鐢4瀛楄妭锛屼篃灏辨槸32浣嶏紝鏈夋晥浣嶆暟涓7浣嶏紝灏忔暟鐐瑰悗6浣嶃傚弻绮惧害鏁帮紙double鍨嬶級鍦32浣嶈绠楁満涓瓨鍌ㄥ崰鐢8瀛楄妭锛屼篃灏辨槸64浣嶏紝鏈夋晥浣嶆暟涓16浣嶏紝灏忔暟鐐瑰悗15浣嶃
  • 扩展阅读:3.0是单精度还是双精度 ... 1.0为什么是双精度 ... 5.0为啥是双精度 ... 怎么判断单双精度 ... 单精度双精度举个例子 ... 双精度double浮点型 ... 单精度为什么不直接用双精度 ... 为什么3.4是双精度 ... 100.0是单精度还是双精度 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网