Numerical representation in computer

Respect to On the Primitive Code, Inverse Code, Complement Code and Shift Code of Operating System and 原码, 反码, 补码 详解(博客园) and 原码、反码、补码及位操作符,C语言位操作详解

Binary machine code

Any data exists in the form of binary machine code in a computer. The first number is used to represent the positive and negative values: 0 is positive and 1 is negative.

in the form of: 以...形式

Numerical representation in computer

Original Code

The value represented by machine code is called the original code.

Inverse Code

Inverse code is generally the least useful representation of computer.
The inverse code of positive numbers is the original code itself. The inverse code of negative numbers: the number of the sign bits is the first bit remains unchanged (符号位保持不变), and the rest of the bits are reversed.
For example, if the original code of + 2 is 00000010, then the inverse code of + 2 is 00000010. The original code of – 2 is 10000010, and the inverse code is 1111101.

Complement Code

Complement is one of the most frequently used encoding methods in computer numerical operations.
The positive complement is the original code itself, which is the same as the inverse code. The complement of negative number is the result of it's inverse code + 1. For example, the complement of + 2 is 00000010. The complement of – 2: 11111111101 (counter code) +1 = 11111111110.

Frameshift

Shift code is to add a bias constant to the value. When the number of coding bits is n, it usually shifts to the N-1 power of 2. For example, the shift code of – 2 = the 7th power of the original code + 2 = 00000010 + 10000000 = 10000010, which can be used as the complement of – 2 11111110
Sign bits remain unchanged and the remaining bits are reversed + 1

Why are there complements and countercodes?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.
于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

为了解决原码做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.

于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-2^31, 2^31-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

位运算

因为位运算的操作值要求是整数,其结果也是整数,所以经过位运算的都会自动变成整数 在JavaScript中可以通过两次取反 ~~去除小数部分,~~1.1 === 1, ~~(-.1.1) === 1

运算符功 能运算规则
&按位与对应位均为 1 时,结果才为 1
|按位或两位中只要有一位为 1,结果为 1。只有两位同时为 0 时,结果为才为 0。
^按位异或两位相异时,结果为 1;两位相同时,结果为 0。
<<左移将运算数的各二进制位均左移若干位,高位丢弃(不包括 1),低位补 0,每左移一位,相当于该数乘以 2。
>>右移将运算数的各二进制位均右移若干位,正数补左补 0,负数左补 1,右边移出的位丢弃。
~按位取反0 变 1,1 变 0。

二进制 十六进制表示法

十进制二进制十六进制
00b00x00
10b10x01
20b100x02
30b110x03