1.      初始题目

面试题:不用额外的变量,实现一个Swap函数,交换两个参数的值(问题1)

这个题目太经典,也太简单,有很多人都会不假思索结出答案:

//Code 1
void Swap(int* a, int* b)
{*a = *a + *b;*b = *a - *b;*a = *a - *b;
}

但真正的难点来了,接下来,就会有面试的第二问:指出code1算法的问题,并修正(问题2)

2.      错误思路

一些毁人不倦的书,把其中的问题归结到了溢出(overflow)。修改方法是用异或替代加减,即:

//Code 2
void Swap(int* a, int* b)
{*a = *a ^ *b;*b = *a ^ *b;*a = *a ^ *b;
}

诚然,在很多场合,大数的加法都会带来溢出的问题。但Code1 中的Swap函数真会构成溢出问题么?(问题3)

2.1 错误的想法

大家都能清楚的描述加法溢出的产生原因:运算结果超出了变量的表示范围。

发生溢出时,结果会是多少呢?有很多人是知道的,但可能表述得不太清晰:舍弃超出变量内存范围的高位(加法只会舍弃最高位),保留在范围内的低位。

用这个概念,去分析问题3,恐怕是很难得到明确的答案的。很多人简单看看,认为执行两个很大的数的加法后,运算结果丢了最高位,所以会构成问题。

和问题3的知识点相同的,有另外一个问题:

判断两个int型变量相加,是否会溢出?不会溢出返回0,否则返回非0整数。下面的方法是否可行?(问题4)

//Code 3
int IsOverFlow(int x, int y)
{int sum = x + y;return (sum - x == y) && (sum - y == x);
}

对问题3,回答“会构成问题”的同学。回答问题4时,应该会认为“方法可行”。理由是,认为溢出后,信息丢失,以后的运算都不再能得到正确结果。

2.2  加法的溢出

事实上,问题3的答案是:不会溢出;问题4的答案是:方法不可行。

用一下数学符号表述,可以清晰的得到正确答案。

假设一个整型变量有w位,那么,整型变量的表示范围是: -2w-1 ~ 2w-1-1。 当求和结果超出这个范围时,就发生溢出。即正数的绝对值大于2w-1-1时,发生正溢出,负数绝对值大于2w-1时,发生负溢出

加法的溢出,只会发生在两个求和参数同正负符号的时候。

第w-1位

(符号位)

第w-2位

第w-3位

…………

第2位

第1位

第0位

一正一负时,肯定不会发生溢出,因为这时:|x +y| < max{|x|, |y|}

对于两个很大的正数相加,发生正溢出时,第w-1位肯定为1,假设除去最高位时,剩下w-1位(第0至w-2位)的内存可以表示为数:r。即 x + y = r + 2w-1

由于是有符号数,第w-1位是符号位,由于符号位是1,说明结果是负数,采用补码,即运算结果为:sum =- (2w-1 – r) = r-2w-1。即于sum = r + 2w-1-2w=x + y - 2w

同时,两个绝对值很大的负数相加,发生负溢出后的结果是: s = x + y + 2w

当两个正数产生加法溢出时,运算结果s = x + y – 2w。 此时, s < 0。

再做减法:s – x = x + y - 2w - x = y + 2w 由于|y| <2w-1,有 |y - 2w| >2w-1 ,发生负溢出,在结果上又加上了 2w。即,x + y - 2w – x + 2w ,这个结果等于y。

因此问题3的答案是“不构成问题”,问题4的答案是:不可行。

判断两个int型变量相加,是否会溢出?不会溢出返回0,否则返回非0整数。这个函数需要怎么设计?(问题5)

发生正溢出后,结果将是负数;发生负溢出后,结果将是正数。

因此可以这样做:

//Code 4
int IsOverFlow(int x, int y)
{int sum = x + y;int posOver = (x > 0) && (y > 0) && (x + y < 0);int negOver = (x < 0) && (y < 0) && (x + y > 0);return posOver || negOver;
}

3.      解决问题

回顾一个经典的算法,快排:

//Code 5
void QSort(int a[], int start, int end)
{if (start >= end)return;int lastLessIdx = start;for (int traveler = start + 1; traveler <= end; ++traveler){if (a[traveler] < a[start]){      Swap(&a[++lastLessIdx], &a[traveler]);}      }Swap(&a[lastLessIdx], &a[start]);QSort(a, start, lastLessIdx - 1);QSort(a, lastLessIdx + 1, end);
}

其中用到了Swap函数。但是,直接用code1中给出的Swap函数行吗?

不行。Code1中的Swap函数,没有考虑自己与自己换的情况。当需要自己与自己交换时(快排中lastLessIdx + 1 == traveler 时),Code1直接把值变成了0。

因此,修正方法很简单,判断是不是自己在和自己交换即可:

//Code 6
void Swap(int* a, int* b)
{if (a == b)return;*a = *a + *b;*b = *a - *b;*a = *a - *b;
}

转载于:https://www.cnblogs.com/dyllove98/p/3230989.html

从Swap函数谈加法溢出问题相关推荐

  1. java 加法 溢出_关于数字:Java 8 Unsigned Integer加法和潜在的溢出

    我正在从Cay S. Horstmann的"真正不耐烦的Java SE 8"一书中进行练习. 基于Number类的改进的一项练习要求: Write a program that a ...

  2. [转]浅谈缓冲区溢出之栈溢出

    浅谈缓冲区溢出之栈溢出 By 浅墨 发表于 2012-12-02 有段时间没有用windows了,刚一开机又是系统补丁更新.匆匆瞥了一眼看到了"内核缓冲区溢出漏洞补丁"几个字眼.靠 ...

  3. 《Effective C++》item25:考虑写出一个不抛异常的swap函数

    std::swap()是个很有用的函数,它可以用来交换两个变量的值,包括用户自定义的类型,只要类型支持copying操作,尤其是在STL中使用的很多,例如: int main(int argc, _T ...

  4. C++ Swap函数有几种写法?

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104344435 S ...

  5. C++STL中swap函数操作与内存地址改变的简析

    写在前面 这篇文章主要讨论了STL中swap函数在交换2个容器的内容的时候是交换内存还是交换元素的问题.由于博主对C++的学习并不好,如果有什么错误恳请大家提出.下面会有一些代码展示一下swap函数在 ...

  6. stl swap函数_vector :: swap()函数以及C ++ STL中的示例

    stl swap函数 C ++ vector :: swap()函数 (C++ vector::swap() function) vector::swap() is a library functio ...

  7. stl swap函数_C ++ STL | vector :: swap()函数与示例

    stl swap函数 C ++ STL vector :: swap()函数 (C++ STL vector::swap() function) vector::swap() function is ...

  8. c语言 swap交换函数_重审C中老生常谈的swap函数交换数值

    概览 本文内容是关于C语言参数传值,以及x86底层实现的计算机科学. 包含了原理速览以及代码示例. 引言 如果你学习过C,可能会对经典的swap函数问题记忆深刻.简单的参数传值并不能在函数外部完成两个 ...

  9. 编程实现 带符号加法溢出判断

    //带符号加法溢出判断 #include<iostream> using namespace std; int tadd_ok(int x,int y) {int sum=x+y;int ...

最新文章

  1. Codeforces Beta Round #2 B. The least round way
  2. 大型网站的负载均衡器、db proxy和db
  3. matlab画图plot设置字体_R语言科研画图字体格式设置
  4. irobot擦地机器人故障_33款扫地机器人口碑:售价6350元的戴森口碑垫底,小米、科沃斯谁更好用?...
  5. BAT脚本每隔30秒创建一个512兆文件(测试磁盘监控用)
  6. 在国内使用DNS服务器的一个对比分析
  7. VMware16下载与安装
  8. 用spss进行数据的标准化处理_用spss怎样对数据进行标准化
  9. kubeedge源码分析
  10. 辩论技巧与逻辑思维_在IT团队中促进富有成效的辩论的3种基本技能
  11. 人脸识别:Contrastive loss和梯度推到
  12. android屏幕重力感应器,android屏幕重力感应如何实现,很质量的一个问题
  13. 高德地图标记文字修改样式_地图标注有哪些优势?如何进行地图标注?
  14. 求一个网页设计作业——个人博客(HTML+CSS)
  15. 发布 PAIRED:一种生成对抗环境的全新多智能体方法
  16. java 亚马逊 mws_使用Amazon Deep Java库进行Java中的机器学习
  17. Python数据可视化,Pyecharts库,外圆环内饼图制作
  18. 前端入门 02:HTML入门
  19. 願いをドラッグの若返り薬)作者紫猫刘程
  20. 论文阅读23 - Mixture Density Networks(MDN)混合密度网络理论分析

热门文章

  1. python下载大文件-python 大文件
  2. python xpath语法-Python爬虫——bs4、xpath基本语法
  3. python3项目-Python3基础教程(十九)—— 项目结构
  4. python工程师一个月多少钱-苏州工业园区学编程大概多少钱一个月
  5. 自学python后能干什么-学习python后能做哪方面的工作
  6. python和php-PHP和Python如何选择?或许可以考虑这三个问题
  7. python入门需要多久-零基础小白多久能学会python
  8. python自带的shell是什么-python中执行shell的两种方法总结
  9. 人脸口罩识别——人脸添加口罩方法masked_faces
  10. windows或Ubuntu中请求github.com请求超时,或在下载GitHub文件出现:<urlopen error [Errno 110] Connection timed out>