水电电工知识
电工知识|RND指令执行出错的原因分析
2016-05-26  浏览:39
水电之家讯:网友ktissot在用下面3条指令将浮点数转换为双整数时,发现了一个神秘的现象。

L MD0

RND //浮点数四舍五入

T MD4

我们知道,最大的正的双整数是2147483647,大于这个数,RND指令转换会出错。

但是他的帖子说实际上能转换的最大的浮点数不是2147483647.0,而是2147483583.0。

这一段本应正常转换的区间转换会出错,为什么转换出错的分界点是2147483583.0,这里面隐藏了什么秘密?

这件事引起我极大的兴趣,为此我用仿真做了大量的实验,下面是我做实验发现的更多的现象:

1.转换出错的情况

RND指令的帮助中说:“如果超出允许范围,则状态位OV和OS被置位为1。结果存在累加器1中”。“出现错误(使用了不能表示为32位整数的NaN或浮点数)时不执行转换并显示溢出。”。

下图用程序状态监控状态字STATUS WORD。

大于2147483647.0时转换出错。

大于2147483584.0到2147483647.0这一段照理说在应该在能转换的范围里,但是转换也会出错,状态字的OV和OS位(第4、5位)被置位为1(见下图)。MD4中是没有转换的浮点数,而不是双整数。转换出错的分界点是2147483584.0。

2.转换成功的情况

小于16777215.0左右转换结果完全正确。转换成功时OV和OS为0。

小于2147483584.0到16777215.0这一段可以转换,但是转换有误差。

接近2147483584.0时,最大误差为64。

大于2147483456.0 ~ 2147483584.0时(区间范围为128.0),转换后得到的双整数均为2147483520(16#7FFF FF80,见下图)。转换结果2147483520是区间中点的值,(2147483456 + 2147483584)/2= 2147483520。

大于2147483328.0 ~ 2147483456.0时,转换后得到的双整数均为2147483392(16#7FFF FF00)。

大于2147483200.0 ~ 2147483328.0时,转换后得到的双整数均为2147483264(16#7FFF FE80)。

经过分析,我已经找到了上述现象的原因,结果暂不公布,希望有兴趣的网友一起来分析一下,共享解决问题的快乐。

3.转换结果分析

大于2147483456.0 ~ 2147483584.0时转换后得到2147483520(16#7FFF FF80)。

大于2147483328.0 ~ 2147483456.0时转换后得到2147483392(16#7FFF FF00)。

大于2147483200.0 ~ 2147483328.0时转换后得到2147483264(16#7FFF FE80)。

上述3个区间内部的间隔为128.0,转换结果为区间的中点(2147483456 + 2147483584)/2= 2147483520。

所以这种转换并不精确,最大误差为128/2=64。

浮点数转换为双整数的转换误差的根本原因是32位浮点数和32位双整数的有效位数的差异造成的。

浮点数由一位符号位、8位指数和尾数的小数部分(23位)组成。尾数的位数决定了浮点数的精度。尾数的整数部分为1,小数部分为23位,所以尾数的有效数字为24位。

双整数除去一位符号位,其有效位数为31位,因此浮点数的有效位数比双整数少7位。

2147483456.0 ~ 2147483584.0相差128.0,它们对应的整数为31位有效数字,这些浮点数输入plc后,因为浮点数的有效位数只有24位,它们的尾数相同,对应的十六进制表示的浮点数均为16#4EFF FFFF,或2.17484e+009(注意有效尾数为十进制7位,而不是对应的整数的10位)。所以转换为双整数后均为2147483520。

ktissot网友说:“这就像看一片湖水一样,你可以看到水和浪花,但是绝对看不到水分子。”由于有效位数较小,浮点数不能分辨“水分子”2147483457.0 ~ 2147483584.0,我们只能看到“浪花”2147483520(16#7FFF FF80)。

如果浮点数较小,例如小于16777215(16#FF FFFF),整数部分只有24位,转换后就没有上述的误差了。在此基础上增大,整数部分的位数越大,误差越大。

因为有效位数相差7位,在接近双整数最大值的区段,浮点数的尾数相差一个数时,转换为双整数后,相差128。2的7次方等于128。

4.高端转换出错的原因分析

为什么最高端大于2147483584.0的数不能正确地转换呢?请注意小于2147483648.0到大于2147483584.0这段范围刚好是64.0(128.0的一半)。RND指令在转换时将这段范围的尾数四舍五入后,尾数的最低位加1,相当于转换后的整数加128(16#80),由上述的16#7FFF FF80(2147483520)加16#80后变为16#8000 0000,超出了双整数整数的允许范围,产生了溢出,所以转换出错。

水电之家为您提供最全面的管材,管件,水电,电线,电工,管材水电品牌的装修知识点和各种管材水电的导购与在线购买服务,拥有最便宜的管材水电价格和最优质的售后服务,每天都有秒杀的抢购活动哦!敬请登陆水电之家:http://shuidian.jc68.com/
更多»您可能感兴趣的文章:
更多»有关 电线 的产品:
  • 水电电工资讯
  • 发表评论 | 0评
  • 评论登陆
  • 移动社区 天花之家 木门之家 灯具之家 铁艺之家 幕墙之家 五金头条 楼梯头条 墙纸头条 壁纸头条 玻璃头条 老姚之家 灯饰之家 电气之家 全景头条 照明之家 防水之家 防盗之家 区快洞察 建材 枣庄建材 临沂建材 南昌建材 上饶建材 抚州建材 宜春建材 吉安建材 赣州建材 鹰潭建材 新余建材 九江建材 萍乡建材 景德镇陶瓷 石家庄建材 衡水建材 廊坊建材 沧州建材 承德建材 建材之家 企业之家 720全景
    (c)2015-2017 Bybc.cn SYSTEM All Rights Reserved