C浮点数精度丢失问题.docx

  1. 1、本文档共3页,可阅读全部内容。
  2. 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
C#浮点数精度丢失问题 C#中的浮点数,分单精度(float)和双精度(double): float 是 System.Single 的别名,介于 -3.402823e38 和 +3.402823e38 之间的 32 位数字, 符合二进制浮点算法的 IEC 60559:1989 (IEEE 754) 标准; double 是 System.Double 的 别 名 , 介 于 -1.79769313486232e308 和 +1.79769313486232e308 之间的64 位数字,符合二进制浮点算法的 IEC 60559:1989 (IEEE 754) 标准; 我们知道,计算机只认识 0 和 1,所以数值都是以二进制的方式储存在内存中的。 (对于人脑和计算机哪个聪明,个人更倾向于选择人脑,计算机只是计算得快,而且不厌其烦而已!) 所以要知道数值在内存中是如何储存的,需先将数值转为二进制(这里指在范围内的数值)。 根据 IEEE 754 标准,任意一个二进制浮点数 V 均可表示为:V = (-1 ^ s) * M * (2 ^ e)。其中 s ∈ {0, 1};M ∈ [1, 2);e 表示偏移指数。 以 198903.19(10) 为 例 , 先 转 成 二 进 制 的 数 值 为 :0011000010100011(2) ( 截取 16 位小数 ), 采用科学记数法等 于 1.100001000111101110011000010100011 * (2 ^ 17)(整数位是 1),即 198903.19(10) = (-1 ^ 0) * 1.100001000111101110011000010100011 * (2 ^ 17) 。 整数部分可采用 除 2 取余法,小数部分可采用 乘 2 取整法。 从结果可以看出,小数部分 0.19 转为二进制后,小数位数超过 16 位(我已经手算到 小数点后 32 位都还没算完,其实这个位数是无穷尽的)。 由于无法得到完全正确的数值,这里就引申出浮点数精度丢失的问题: /* 程序段 1 */ float num_a = 198903.19f; float num_b = num_a / 2; Console.WriteLine(num_a); Console.WriteLine(num_b); 这段程序代码,我们预想中正确的结果应该是:198903.19 和 99451.595。 但结果居然是 !!原因下面将讲到 ... 这里介绍另一种转小数部分的方法,有兴趣可以看下: 假如结果要求精确到 N 位小数,那么只需要将小数部分乘以 2 的 N 次方(例如 N = 16,0.19 * (2 ^ 16),得到 12451.84)。 取整数部分(12451),按整数的方法转为二进制,得到 11000010100011,不足 N 位在高位用 0 补足。 结果 0.19 精确到 16 位后,用二进制表示为 0.0011000010100011。 可以看出,若是小数部分乘以 2 的 N 次方后,可以得到一个整数,那么这个小数可以用二进制精确表示,否则则不可以。 (原理很简单,根据二进制小数位转十进制的方法,反推回去就可以得到这个结果) 在内存中,float 和 double 的储存格式是一致的,只是占用的空间大小不同。 float 总共占用 32 位: 从左往右,第 1 位是符号位,占 1 位;第 2-9 位是指数位,占 8 位;第 10-32 位 是尾数位,占 23 位。 double 总共占用 64 位,从左往右第 1 位也是符号位,占 1 位;第 2-12 位是指数 位,占 11 位;第 13-64 位是尾数位,占 52 位。 其中,符号位(即上文的 s,下同),0 代表正数,1 代表负数。 对于 float,8 位指数位的值范围为 0-255(10),由于指数(即上文的 e,下同)可正可负,而指数位的值是一个无符号整数。根据标准规定,储存时采用偏移值(偏移值为127) 的方法,储存值为指数 + 127。例如 0111 0011(2) 表示指数 -12(10() 1011(2) 表示指数 12(10)(12+ 127 = 139)。 { (-12) + 127 = 115),1000 另外,IEEE 754 规定(同样适用于 double): 当指数全为 0 时,如果尾数全为 0,表示 ±0(正负取决于符号位),如果尾数不全为 0,计算时指数等于 -126,尾数不加上第一位的 1,而是还原为 0.xxxxxx 的小数,表示更接近 0 的小数; 当指数全为 1 时,如果尾数全为 0,表示 ±无穷大(正负取决于符号位),如果尾数不全为 0,

文档评论(0)

hao187 + 关注
官方认证
内容提供者

该用户很懒,什么也没介绍

认证主体武汉豪锦宏商务信息咨询服务有限公司
IP属地湖北
统一社会信用代码/组织机构代码
91420100MA4F3KHG8Q

1亿VIP精品文档

相关文档