对汇编语言中负数舍入误差的理解
来源:互联网 发布:淘宝让上传身份证清关 编辑:程序博客网 时间:2024/04/25 21:21
在看汇编语言中有符号数与无符号数的表示时看到一道这样有关于2的幂次方除法的题目。结果发现,又不会了。。。。然后在网上各种找资料,把视频进度跳回去看了好几遍还是没看懂,后来自己在草稿纸上比划了半个小时,终于懂了个大概。因为网上的资料讲解得都很笼统,所以写下这篇博文为方便日后复习。
我遇见的问题如下:
问题:
在我们平时的算数运算逻辑中,做除法若需舍弃小数点后数字,那么结果总是向0的方向舍入的,(例如:2.9舍入为2;-2.9舍入为-2),即向浮点数所在两个整数区间中最接近0的那个整数舍入。但是在计算机中,舍入的方式有所不同。在大多数的机器中,除法要比乘法还有加法这些运算都要慢很多倍(毕竟先分解为减法,再分解为加法),计算机中对于2的幂次这种数很是敏感,因为计算机当中用到的指令和进制本来就是二进制的形式,计算机用这种方式运算是最快的。所以,在做除法时如果除数是2的幂次,那么可以直接通过对数字的编码进行移位来解决。也就是说 如果除数是2的k次幂,那么我们就会把被除数相应的做算数右移操作,右移k位。这样的结果和平时我们做除法的结果是一样的。例如:1011(十进制的11)除以2结果为101.1。若将小数点后舍去则为101(十进制的5),这样的结果和我们平时运算的逻辑是相符的。但在上面那张图片中我们却发现-7606.5按照正常逻辑舍入后应为-7606但计算机结果却是-7607,-950.8125也变成了-951.这是为什么呢?
我找到的答案:
发生舍入错误的两个结果均为负数,后发现问题的产生与负数在计算机中的补码编码方式有关。正数的编码方式即将10进制数转化为二进制,而负数在计算机中采用补码方式编码简单来讲就是把正数的原码所有位置取反再加一。还是以上文中的11为例,其二进制表示为1011,补码表示只需在前面添加符号位0即可为01011。对11补码取反得10100再加一为10101,这就是-11的编码。
再谈除以2的n次幂,以一次为例:
11/2=5.5,二进制0011.1,舍去0.1为0011即5
这里可以看到增加小数点后数字可令正数绝对值增加
-11/2=-5.5,二进制1101.0,这时如果对其加0.1则为1101.1,转化为10进制就是-5
所以对于负数而言增加小数点后数字可令其绝对值减小
看到这里答案已经出来了,-7606.5将其二进制小数点后数字去掉后使得其绝对值变大,因此导致舍入值为-7607.
解决方法:
在除以2的n次幂之前加上一个(2^n)-1.
原理:发生舍入错误的负数在除以2的n次幂后,小数点向左移动n位,并且所得结果小数点后不全为0.加上(2^n)-1后在小数点前一位处发生进位,使得原结果绝对值减少1,从而消除舍入误差
- 对汇编语言中负数舍入误差的理解
- c语言中double转int的舍入误差
- Pose-Graph SLAM 中对误差函数的理解
- 实型数据的舍入误差
- 浮点型数据的舍入误差
- 谈谈对泛化误差的理解
- 舍入误差
- 理解ADC误差对系统性能的影响
- 汇编语言中对PSP区和程序区的一些理解
- js数字舍入误差以及解决方法
- mysql 存储过程中对负数的捕捉
- ADC中的ABC:理解ADC误差对系统性能的影响
- ADC中的ABC:理解ADC误差对系统性能的影响(转载)
- 计算机对负数的表示
- 对viewstates的理解更深入了(1)
- 对viewstates的理解更深入了(2)
- ECMAScript浮点数值计算舍入误差问题
- 关于汇编语言中传送指令存在一些限制的理解
- java 生成验证码
- 手机端通过Es文件浏览器访问windows服务器用File Zilla Sever软件 分享的文件
- TCP三次握手及四次挥手详细图解
- poj 1066 Treasure Hunt (线段相交判定)
- 迷宫day3
- 对汇编语言中负数舍入误差的理解
- Palindrome Partitioning II
- 秒杀系统中如何动态生成下单随机URL
- NoSQL 非关系型数据库简介
- 计算广告系列篇(5)------计费
- 私有云的迁移:从VMware到OpenStack
- static_cast、dynamic_cast、const_cast和reinterpret_cast总结
- 【寒江雪】Direct3D11纹理贴图
- DOS常用命令