• 20180315 代码错题(3)


    1
    2
    3
    4
    5
    void swap_int(int *a,int *b){
      *a=*a+*b;
      *b=*a-*b;
      *a=*a-*b;
    }
    以下说法正确的是:
    结果不正确,因为会溢出,用位与的方式就没问题
    结果正确,即使会溢出
    结果正确,不会溢出
    其他选项都不对

    答案 B  错选 A
    设整形变量*a、*b的位表示为
    *a = n31n30 ··· n0
    *b = m31m30 ··· m0
    只有当*a > 0 && *b > 0 或 *a < 0 && *b < 0时才会发生溢出。两者类似,只证明均大于0时的情况。必须扩展额外一位才能够容纳正确的结果,'|'左边为扩展位。
    *a = 0|0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20 = N
    *b = 0|0m30 ··· m0 = m30*230 +  m29*229 + ··· + m0*20 = M
    若和溢出,则33位表示必为
    *a + *b = 0|1b30 ··· b0 = -231 + b30*230 +  b29*229 + ··· + b0*20 =  2 31  + B ① 
    计算机将得到的33位结果truncate回原来的32位,即丢弃第33位(0)变为:
    *a + *b =    1b30 ··· b0 = -231 + b30*230 +  b29*229 + ··· + b0*20 = -2  31   + B ②
    正确的真实值是①,溢出结果为②,可见溢出结果=真实值-2 32 
    则*b = *a - *b = ② - *b =  ① - 232 - *b = *a + *b - 232 - *b = -232 + *a
    最后一步,来看 -232 + *a  == *a 成立否?
    0 < *a < 231, 则 -232 < -232 + *a < -231,和仍需要扩展1位方能表示:
    *a    = 0|0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20 = N
    -232 = 1|0000 ··· 00
     和的位表示为
    -232 + *a = 1|0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20
    同样,计算机把33位结果truncate回32位(丢弃第33位)得到:
    -232 + *a =  0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20 = *a
    可见-232 + *a  == *a 是成立的。因此尽管溢出了,但仍能正确交换。
  • 相关阅读:
    uniapp、小程序之swiperitem内容过多显示不全的解决方案
    PingFang(苹方)字体的引用
    Vue项目中使用websocket
    uniapp页面跳转传递参数过长
    uniapp开发的h5,使用微信授权登录(前置条件+具体代码)
    Maven工具安装使用
    Lombok代码生成插件使用
    对不起,我的文章暂时无法公开!
    [iOS]学习笔记7(CATransform3DFlip效果)
    [iOS]学习笔记8 (iOS之阻塞)
  • 原文地址:https://www.cnblogs.com/kxzh/p/8574805.html
Copyright © 2020-2023  润新知