c语言:取绝对值

假设我们有一个 long 类型的变量 l,我们希望恢复其绝对值。以下是两种方法的对比:

方法1:使用条件语句

这个很好理解,负数时取负运算 ,用于数值的符号反转。

复制代码
long abs_value(long l) {
    if (l < 0) {
        return -l;
    } else {
        return l;
    }
}
方法2:使用位操作
复制代码
long abs_value(long l) {
    long s = l >> 63;  // 获取符号位
    l = (l + s) ^ s;   // 恢复绝对值
    return l;
}

l为正数时,s=0; (l+s)^s = l^0=l;对于任何整数与 0 进行按位异或操作的结果总是 其本身。

l为负数时,s=-1,即0xffff ffff ffff ffff;

这是因为long l的最高位为符号位,负数的最高位为1;右移操作会将变量的二进制表示向右移动指定的位数,空出的位数会用符号位的值来填充,l>>63,左侧空位全补1就得到0xffff ffff ffff ffff,该值对应-1。

在计算机中,负数以补码的形式表示。对于一个负数 x,其补码表示为:

  1. 取反(按位取反)。

  2. 加1。

s=-1时, (l+s)^s = (l-1)^0xffff ffff ffff ffff 正好是负数取补码的逆过程,所以相当于获取了负数的绝对值。

方法2的优势:

1. 避免条件分支

使用条件语句(如 if 语句)会导致代码中出现分支。在现代处理器中,分支预测失败可能会导致性能下降。通过使用位操作,可以避免条件分支,从而提高代码的执行效率。

2. 提高性能

位操作通常比条件分支更快,因为它们直接在寄存器级别进行操作,而不需要进行复杂的控制流判断。这在性能敏感的应用中尤其重要。

3. 减少代码复杂性

虽然位操作可能看起来有些复杂,但它们实际上可以减少代码的复杂性,特别是在处理整数操作时。位操作通常更简洁,且不需要额外的变量或复杂的逻辑。

但是实际测试时,还是方法1的性能更高一些:

复制代码
xxx@:~/test/c-func$ ./a.out
Time taken by abs_value_if: 4.517215 seconds
Time taken by abs_value_bit: 4.865139 seconds
相关推荐
matlab代码2 分钟前
基于matlab自助水果超市水果识别收费系统(GUI界面)【源码67期】
开发语言·matlab
Navigator_Z3 分钟前
LeetCode //C - 1240. Tiling a Rectangle with the Fewest Squares
c语言·算法·leetcode
稻米哟3 分钟前
力扣100——双指针
算法·leetcode
hui-梦苑17 分钟前
[PHP]轻量主题函数WordPress 集成 KaTeX 数学公式渲染
开发语言·php·wordpress·katex
大圣编蚕30 分钟前
Java StringWriter 详解:从入门到实战
java·开发语言·python
码行山野赴时序归途34 分钟前
C语言预处理指令:编译前的“幕后导演“
c语言·开发语言
golang学习记40 分钟前
Go 1.27新特性: json/v2使用有趣指南
开发语言·golang·json
老苗项目实战1 小时前
Java工程师高频面试题(基于近一年的真实面试记录整理)
java·开发语言·面试·预见猿份·老苗项目实战
小小、码农1 小时前
C++11右值引用与移动语义 —— 从拷贝资源到转移资源
开发语言·网络·c++·网络协议
明志数科2 小时前
具身智能真机采集工程实践:5类高频失效模式与规避清单
人工智能·算法·机器学习