由C++绝对值函数想到的
来源:互联网 发布:淘宝图片保护怎么开通 编辑:程序博客网 时间:2024/06/06 09:00
这些天恰好要用到一个绝对值的函数。好吧,你会说这个直接用std::abs不就行了吗?对的,一开始我也是这样用的。但是如果去求最小的那个int的值的绝对值,就会导致输出不正确。如:
int min_int = -2147483648;cout<<std::abs(min_int)<<endl;得到的结果仍然是-2147483648!恰好我的程序有可能出现这样的情况。所以需要自己去完成一个。
1、第一个版本:
unsigned int __abs(int value){ return (value >= 0) ? value : -value;}仍然是std::abs的老路,不可取!
2、第二个版本:
#include <limits>unsigned int __abs(int value){ return (std::numeric_limits<int>::min() == value || value >= 0) ? value : -value;}这个版本比较简洁,可移植性也很高。std::numeric_limits<int>::min()返回当前系统下int值的最小值,能够自适应int的内存宽度返回准确的值。当value和最小的int值相等或者value不为负数时,我们直接进行位对位的拷贝——因为unsigned int没有符号位,所以完全可行的。当value为除最小值外的负数时,直接取相反数即可。
但这个版本需要用到两次条件判断,能不能再优化一下呢?所以出现了:
3、第三个版本:
unsigned int __abs(int value){ unsigned int copyed_value = value; return (copyed_value > 0x80000000) ? -value : copyed_value;}因为32位下最小的int值为0x80000000——最高位符号位为1。当位对位拷贝到unsigned int中时,仍然是这个值。但其他的负数除了最高位为1外,其余位置也有值,比如-1的16进制表示为:0x80000001。所以,我们先执行位对位的拷贝,到copyed_value中。所以出现了判断情况:
(1)如果copyed_value是大于0x80000000的,说明value是负数,所以我们直接取相反数(-value);
(2)如果copyed_value是等于0x80000000的,说明value恰好是最小的那个负数,执行位对位拷贝后,copyed_value中存放的就是value的绝对值,所以返回copyed_value;
(3)如果copyed_value是小于0x80000000,说明value为正数。直接去alue或者copyed_value即可。
通过分析,我们将(2)和(3)合并到一起,返回copyed_value。所以,采取第三种方案,就只有一次比较操作。比第二种方案省一次。但是这种方案第一眼看去可能易读性上不是很好。
权衡三种方案,应该说各有利弊。三种情况各有适用的地方。如果你的函数不考虑最小int值的绝对值,可以采用std::abs即可;如果需要考虑但不必担心性能问题,那么第二种方案是你最好的选择!但如果你既要考虑最小int值的绝对值问题,又要考虑性能问题,建议采用第三个方案。
这个问题虽然简单,但里面透射出来的东西可真不少。其实我们在编程工作中,从细节出抓起,往往能够获得很多收获。
【转载请注明出处】
- 由C++绝对值函数想到的
- 由C中函数调用的函数声明想到的
- 由GetDlgItem函数想到的
- 由rand()函数想到的
- 由函数clock想到的
- 由C语言想到的
- 由inline想到的【C++/C】
- 由函数想到的生活哲学
- 由strcpy()函数想到的一些
- What:由函数Uri.parse()想到的
- 由C/C++ 争议想到的
- 由C数组array[-1]想到的
- 由C语言指针想到的
- 由uuid_to_string函数想到的C语言函数返回字符串问题
- 由本子想到的
- 由忧郁想到的
- 由电车男想到的
- 由MBV想到的
- Android待机流程分析---锁屏、解锁模块
- Java基础:三步学会Java Socket编程
- Error:Your step-into request resulted in an automatic step-over of a property or operator.
- 将矩形向外扩展一圈,但不超过图片的大小
- 使用SOAP协议修改websphere数据源的密码,测试连接
- 由C++绝对值函数想到的
- trie树
- ORACLE 监听服务启动后又停止了
- python编译pyc和pyo
- 我的女儿昨天会走路了
- 诺基亚为Lumia发布增强现实测试应用City Lens
- linux下SVN的一些基本操作(ubuntu)
- 10.04下编译BlueZ,glib2.18.1出现`g_malloc0_n'错误
- 线程