首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员数学 —— 二进制

程序员数学 —— 二进制

作者头像
solve
发布2019-10-30 19:15:59
7880
发布2019-10-30 19:15:59
举报

前言

常年浪迹与各种高级语言的我们,是否还记得哪些基础中的基础呢? 今天就让我们一起来回忆一下计算机的那一串 0101010101 —— 二进制 吧!

通过本文,你将了解到以下几点:

  1. 什么是进制,以及 进制之间 的转换
  2. 计算机为什么要用二进制
  3. 了解位运算,以及 逻辑运算 和 算术运算的 区别

什么是进制?

十进制

  • 十进制 是以 0-9 为基础数字系统, 是在世界上应用最广泛的进位制。 具有以下几个特点:
    1. 高位在左,地位在右
    2. 每个位上只有 0-9 十个数字
    3. 高位的 1 代表低一位的 10,即: 第0位表示
    (0-9)*10^0
    (0-9)*10^0

    第一位表示 基本的

    (0-9)*10^1
    (0-9)*10^1

    第二位表示 基本的

    (0-9)*10^2
    (0-9)*10^2
  • 十进制数字 123 可以这么来表示
123 = 1*10^2 + 2*10^1 + 3*10^0
123 = 1*10^2 + 2*10^1 + 3*10^0

其中 任何非 0 的数的 0 次方都是 1. 至于这个写法就不多解释了,相信你一看就懂....

平时生活中我们的计算基本都是基于 十进制,比如 1+2=3 ,5+6=11 有时候我们不禁也会想一下:为什么 1+2 会等于 3 呢? 那么我们可以想想,你吃了一个苹果,又吃了两个,那么你一共吃了几个? 所以,其实算术没那么多弯弯道道,都是源于真真实实的生活。

二进制

看完十进制,那么二进制其实就很好类比了.....

  • 二进制 是以 0-1 为基础数字系统,是计算机应用的进位制。 具有以下几个特点:
    1. 高位在左,地位在右
    2. 每个位上只有 0-1 二个数字
    3. 高位的 1 代表低一位的 2,即: 第0位表示
    (0-9)*2^0
    (0-9)*2^0

    第一位表示 基本的

    (0-9)*2^1
    (0-9)*2^1

    第二位表示 基本的

    (0-9)*2^2
    (0-9)*2^2
  • 二进制数字 101 可以这么来表示
5 = 1*2^2 + 0*2^1 + 1*2^0
5 = 1*2^2 + 0*2^1 + 1*2^0

其中 任何非 0 的数的 0 次方都是 1. 我们可以看到,101 的 十进制 就是: 5

  • 通过上面的,我们应该很容易就可以将 任意进制的数字 转换成 十进制的 数字了

关于十进制转其他进制....使用计算机其实是很好弄的,不过如果你想具体去了解怎么自己算,那么还是去自己找点资料吧,当然,也许后面我们可以来讨论下

为什么计算机要用二进制?

这里我大概列举我知道的几点

  1. 简单,二进制只有 0 和 1 两种状态,可以使得计算机的运算变的非常简单, 并且能满足电路的一开一关。
  2. 适合位运算,针对位运算比平时的运算具有更高的效率
  3. 具有比较好的容错 和 抗干扰能力,多进制会导致状态增加,使得计算机识别状态的时候更加不容易控制。

这里肯定还有很多其他的原因,限于本人知识有限, 如果你想详细了解这块,还是自己去找找相关的资料看看比较靠谱

位运算

接下来我们就来重点说一下二进制的位运算。

  • 向左移位 定义:用来将一个数的各二进制位全部左移若干位,其右边空出的位用0填补,高位左移溢出则舍弃该高位。 以下是 2 向左移位 1,2,3 的结果: scala> 2 << 1 res1: Int = 4 scala> 2 << 2 res2: Int = 8 scala> 2 << 3 res3: Int = 16 我们可以发现: 向左移 1 位: 4 = 2 * 2^1 向左移 2 位: 8 = 2 * 2^2 向左移 3 位: 16 = 2 * 2^3 大概我们可以得出结论:向左每移动一位,那么就等于 该数 乘以 2 的(移动的位数)次方 ,那么怎么证明呢?
    1. 2 的 二进制是 10
    2. 向左移 1 位: 那个 10 就会变成 100 ,从十进制来看,即:
    a= 1*2^1 + 0*2^0
    a= 1*2^1 + 0*2^0

    转变成了

    b = 1*2^2 + 0*2^1+ 0*2^0
    b = 1*2^2 + 0*2^1+ 0*2^0

    a*2 = b
    a*2 = b

    这样我们也就知道为什么 向左每移动一位,那么就等于 该数 乘以 2 的(移动的位数)次方 了.

  • 向右移位 在我们看了向左移位之后,那么其实向右也就很简单了。
scala> 16 >> 1
res18: Int = 8

scala> 16 >> 2
res19: Int = 4

scala> 16 >> 3
res20: Int = 2

可以看出来,每移动一位就等于 该数 除以 2的(移动位数) 次方,当然这里结果是要求整数

然后你以为移位就是这么简单么?当然不.... 不知道你是否还记得,如果一个值是负数,他是怎么表示的,如果你不记得了, 那么你至少应该记得,在有符号的数字中,二进制的第一位一般都是符号位的。 那么我可以来试试:

scala> -16 >> 3
res21: Int = -2

恩?看起来好像没有问题啊,这个不就是我们期望的么? 确实,看起来确实是我们期望的。但是如果让你现在给这个右移一个定义,那么你该怎么给呢?

如果类比向左位移,那么应该是这样:用来将一个数的各二进制位全部右移若干位,其右边空出的位用0填补,舍弃低位。

那么你是否已经发现问题呢?这个定义好像和我们认知的会有点不一样,如果用 0 填,那么应该会变成正数才对。所以其实右移并不是我们简单的想象的那样,

恩 ,不卖关子了,我们直接说吧....

右移如果是没有符号位,那就没什么好说的了, 如果有符号位,那么右移就会有点不一样,所以右移我们可以分为:

  1. 逻辑右移: 用来将一个数的各二进制位全部右移若干位,其右边空出的位用0填补,舍弃低位。
  2. 算术右移 用来将一个数的除符号位外的各二进制位全部右移若干位,并在符号位之后用符号位 1 填补,舍弃低位。

这样就很清楚了,所以我们可以看到 我们使用的 -16 >> 3 是属于 算术右移 的。 那么逻辑右移是怎么样的呢?

scala> -16 >>> 3
res22: Int = 536870910

所以说 逻辑右移 是>>>, 一个负数直接就被我们移成了一个正数

这里也可以考虑下为什么没有 逻辑左移,这里本人也没有找到标准答案,不过猜测应该是, 逻辑右移,在做左边是要考虑补位的是 1 还是 0,不能使符号发生转变。 而左移不需要,只需要在右边补0,不需要考虑符号转变,或者说在不溢出的情况下,其符号是不会变的。

  • 位运算 将两个二进制数字各个位上的数字进行运算即:位运算,一般可以分为以下几种:
    • 与 参与操作的所有位中都必须是 1,其运算的结果才是 1,否则是 0; 计算操作符一般是 & scala> 4 & 2 & 1 res24: Int = 0 其中 4 的 二进制是 : 100 其中 2 的 二进制是 : 10 其中 1 的 二进制是 : 1
    • 或 参与操作的所有位中如果有一个是 1,其运算的结果就是 1,否则是 0; 计算操作符一般是 |

    ``` scala> 4 | 2 | 1 res25: Int = 7 ```

    • 异或 参与操作的所有位中不能相同,其运算的结果才是 1,否则是 0; 计算操作符一般是 ^

    ``` scala> 4 ^ 2 ^ 1 res25: Int = 7 ``` 这里的计算都是从左向右进行的,和平时的算术运算没什么两样噢! 不过这里需要注意的是....在计算机的运算中,一定要考虑溢出!!! 往往当数据溢出的时候,其产生的问题一般会非常严重,并且某些情况下不太那么容易查

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 什么是进制?
    • 十进制
    • 二进制
    • 为什么计算机要用二进制?
    • 位运算
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档