二进制如何优化代码性能

文章探讨了计算机为何选择二进制作为基础,强调了位运算的效率和在表示复杂信息时的内存节省,如用二进制表示年龄和性别,以及在Java字节码和Android源码中的实际应用实例。
摘要由CSDN通过智能技术生成

计算机为什么用二进制?

因为简单!

计算机的底层是基于晶体管实现的,可以简单地理解为一组开关,打开就表示 1,关闭就表示 0,所以,采用二进制的话,计算机只需要简单地打开/关闭这些开关即可。

事物只有两种状态:有和无!用数字表示就是 0 和 1!

假设我们的计算机有 1 个开关,打开表示天亮,关闭表示天黑;打开表示对,关闭表示错;打开表示 1,关闭表示 0,这种例子有很多。那么如果是十进制呢?用谁表示打开,用谁表示关闭呢?又怎么表示 1,怎么表示 9 呢?太麻烦了!

我们来看二进制的最大优点:位运算。

我们知道:p 与 q 等于取交集,全部为 1 才为 1;p 或 q 等于取并集,全部为 0 才为 0。

OK,现在我们是二进制,只有 0 和 1。那么根据上述法则:

100∩011=000100∩011=000,100∪011=111100∪011=111。

二进制优化性能案例:

有个问题:给定一个数 n,怎么判断 n 是不是 2 的 n 次方呢?很简单啊,直接求余就行了。

void is2Power(int n) {
    if (n <= 0) return false;
    int temp = n;
    while (temp > 1) {
        if (temp % 2 != 0) return false;
        temp /= 2;
    }
    return true;
}

确实很好,但是还能更好。看下面代码:

public boolean isPowerOfTwo(int n) {
    return (n>0) && ((n & (n - 1)) == 0);
}

我们知道,10 的 n 次方最高位是 1,其他位都是 0;2 的 n 次方也是同理。也就是说:如果一个数 a 是 2 的 n 次方,那么 a 的最高位就是 1,其他位全是 0;那么,a-1 呢,就变成高位是 0,其他位全是 1 了。

比如:a = 10000,a-1 就是 01111,根据真值表,我们知道:

10000∩01111=010000∩01111=0

所以如果 a 是 2 的 n 次方,那么就有:

𝑎∩(𝑎−1)=0a∩(a−1)=0

根据这个特性,我们只需要进行简单的按位与运算,就能很快得到正确的结果。这就是位运算的强大之处。大家可以在 leetcode 上试一下,对比下运行速度便知。

灵活运用二进制的位运算不仅能提高速度,熟练使用二进制还能节省内存。

在很多人的认知中,最省内存的就是基本数据类型,也就是布尔值、短整型、byte 类型等。

但是,这不是最省的。比如,我要存储一个人的年龄和性别,我们可以用两个字段:

int age;
boolean isMan;

这大概是所有人的写法了,也确实符合逻辑,但是,我们可以用更少的空间来记录的。我们知道,一个人的年龄最多也就是三位数,一个人的性别要么是男、要么是女,雌雄同体和人妖除外。

那么,一位数就能表示性别,三位数就能表示年龄。也就是说,一个二进制就能表示性别:0 表示女,1 表示男。人的年龄很少超过 120 岁,而一个 byte 最大表示 127,我们用一个 byte 就能表示年龄,一个 byte 是 8 位二进制,那就是说,我们只需要 9 个二进制位就能表示人的年龄和性别。也就是两个 byte。而一个 int 是 4 个 byte 呢,这样我们就直接节省了一半以上的内存。

那么二进制怎么表示一个 32 岁的男性呢?像这样:1_0010_0000,我们用首位的 1 表示性别,后面的 8 位表示年龄。这样只需要两个 byte 就足够。

有人可能会说:这有点小题大做啊,至于吗?

嗯,对于大部分场景,是意义不大的,但是对于一些很多人用的公共库、工程代码以及一些追求极致的设备上,这就很重要了。

比如 Java 的字节码,我们知道,我们写的语言都是最后要跑在 CPU 里面的,而 CPU 只认识机器码,也就是二进制;所以我们写的代码要有个编译过程,Java 语言的这个过程的产物就是字节码文件,这个文件要尽可能紧凑,尽可能小,那么上述的小题就不大做了。

我们可能会看到一些源码里面有很多 flag 变量,对这些 flag 进行按位与或按位或运算来检测标记,从而判断是否开启了某个功能。他为什么不直接用布尔值呢?很简单,这样效率高还节省内存。比如Android源码中的测量过程,就用到MeasureSpec这个类,它是一个int类型,用高两位表示测量模式,用低 30 位表示测量值,这样只用一个变量就保存了多个信息,有兴趣的可以去看下相关源码。

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值