计算机的血肉:数据

为何计算机是基于二进制的

最先人们出现了大量计算的需求,首先经历了人工算而后借助算盘再到步进计算器、差分机、分析机。 计算的需求变得愈来愈大,机器也愈来愈先进,首先由于数学家能够经过逻辑运算进行加减乘除等逻辑运算,而后人们发明了机械继电器来描述状态表述二进制,因为机械的东西故障率很高又经历了热电子管(真空管)-> 晶体管、计算机便开始了快速发展,二进制也成为现代计算机的数据承载标准。html

自从分析机出现后这些计算工具开始了初步编程化,而后出现了打孔机。直到出现冯·诺依曼结构,计算机开始蓬勃发展。java

进制转换

先说一下各个进制的通常的表述方式git

进制名称 Java 中写法 通常表示符号
二进制 0b101 0b 开头是二进制 BIN
八进制 011 0 开头是八进制 OCT
十进制 11 正常数字写法就是十进制 DEC
十六进制 0x11 0x 开头是十六进制 HEX

你们可使用如下语句输出一下看看具体值是多少。算法

System.out.println(0b101);
System.out.println(011);
System.out.println(11);
System.out.println(0x11);
复制代码

二进制与十进制

二进制到十进制:10100 = 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 0 * 2^0 = 20
复制代码

十进制到二进制:
20 / 2 = 10 余 0
10 / 2 = 5 余 0
5 / 2 = 2 余 1
2 / 2 = 1 余 0
1 / 2 = 0 余 1

把余数倒序:10100
复制代码

八进制与十进制

八进制到十进制:12345 = 1 * 8^4 + 2 * 8^3 + 3 * 8^2 + 4 * 8^1 + 5 * 8^0 = 5349
复制代码

十进制到八进制:
5349 / 8 = 668 余 5
668 / 8 = 83 余 4
83 / 8 = 10 余 3
10 / 8 = 1 余 2
1 / 8 = 0 余 1

把余数倒序:12345
复制代码

十六进制与十进制

十六进制到十进制:123BF = 1 * 16^4 + 2 * 16^3 + 3 * 16^2 + B(11) * 16^1 + F(15) * 16^0 = 74687
复制代码

十进制到十六进制:
74687 / 16 = 4667 余 F(15)
4667 / 16 = 291 余 B(11)
291 / 16 = 18 余 3
18 / 16 = 1 余 2
1 / 16 = 0 余 1

把余数倒序:123BF
复制代码

字符编码

本质是根据标准存储十进制索引编号。 哈夫曼最小字符编码(五位 32个值)-> Ascll 编码(7位 128个值) -> Unicode 编码(16位)编程

UTF-8 与 Unicode 的区别

你们看一看阮一峰大神写的这一篇便可。数组

字符编码笔记:ASCII,Unicode 和 UTF-8bash

Base64 原理

首先咱们了解一下 Base64 是什么?最初网络传输有不少特殊字符服务器没法识别,传输起来有些问题,因此发明 Base64 编码来进行转码。服务器

Base64 是使用大小写英文字母各26个、数字10个、加号 + 和斜杠 / 64 个字符来表示数据的编码,除了有以上 64 个符号,还有一个 = 做为后缀。由于只有 64 个有效字符,因此二进制有效位也只有 6 位(00111111 能够表示 64 个数)。网络

Base64 索引表

由于此处咱们是转码文本,因此文本转换二进制是经过 Ascll 码表来转换的,而后每 6 位转换为十进制,而后根据十进制查询 Base64 索引表查询相应字符进行拼接,最后使用 = 表明 6 位去补齐,使位的总长度为 8 的倍数。解码亦如此。app

Base64 的原理看到了,咱们能够戳破几个不正确的说法。

  1. Base64 加密算法,咱们看到了这根本不是什么加密算法,只是编码算法而已,最多使内容不能让人一眼就能记住。
  2. Base64 压缩,压缩也是不对的方法,根据他的实现方式,咱们基本能够算出通过 Base64 编码会使数据增大 1/3。若是是对 Base64 编码后的数据在进行压缩,那就是其余压缩方式了,就不属于 Base64 编码的范畴了。

byte[] 与 十六进制字符串 转换

public static String toHex(byte[] bytes) {
    if (bytes == null) {
        return "";
    }
    final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    // byte 最大值是 255 转成字符串则为 0xFF,因此字符串长度是 byte 数组的两倍。
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for (int j = 0; j < bytes.length; j++) {
        v = bytes[j] & 0xFF; // 取 8 个位
        hexChars[j * 2] = hexArray[v >>> 4]; // 取高 4 位放入 char
        hexChars[j * 2 + 1] = hexArray[v & 0x0F]; // 取低 4 位放入 char
    }
    return new String(hexChars); // 转换为字符串
}
复制代码
public static byte[] fromHex(String s) {
        if (s != null) {
            try {
                StringBuilder sb = new StringBuilder(s.length());
                for (int i = 0; i < s.length(); i++) {
                    char ch = s.charAt(i);
                    // 首先把空格 '\n' '\r' 等特殊字符排除掉
                    if (!Character.isWhitespace(ch)) {
                        sb.append(ch);
                    }
                }
                s = sb.toString();
                int len = s.length();
                // 缘由已经解释过了 byte 数组是字符串长度的 1/2
                byte[] data = new byte[len / 2];
                for (int i = 0; i < len; i += 2) {
                    // 将 char 转换为 int 当作高 4 位
                    int hi = (Character.digit(s.charAt(i), 16) << 4);
                    // 将 char 转换为 int 当作低 4 位
                    int low = Character.digit(s.charAt(i + 1), 16);
                    if (hi >= 256 || low < 0 || low >= 16) {
                        return null;
                    }
                    // 经过位运算合并
                    data[i / 2] = (byte) (hi | low);
                }
                return data;
            } catch (Exception ignored) {
            }
        }
        return null;
    }
复制代码

这个字符串转换 byte 很差理解咱们画张图,来辅助理解下。

媒体编码

全部媒体都是同样的,规范一个媒体格式为表述标准,而后使用相应格式的解析器来解析。

压缩

压缩在咱们平常生活中很常见,通常都是对二进制数据进行压缩,咱们今天为了简单就用简单的字符串举例来说明。

无损压缩

假如文字内容是:你好啊你好你好你好你好你好你好你好你好你好你好

简单定义一个压缩方法,压缩以后就是:1*你好啊,10*你好

经过咱们自定义的算法解压缩就能够还原了,通常公司的压缩算法都是比较复杂的。

有损压缩

咱们如今使用的声音文件存储的都是声音波形。

假设有个声音文件:12 -32 45 23 -54 0 -7 34 37 89 -23 0 -54

有损压缩就是经过某些算法把某些无用的波形删掉,再执行无损压缩,可是解码回来就会少一部分声音。这就是有损压缩。

至于那些波形是无用的,是不少科学家,数学家研究得知。

编程语言基本类型(以 Java 为例)

类型 字节
boolean 1 8
byte 1 8
char 2 16
short 2 16
int 4 32
long 8 64
float 4 32
double 8 64

计算机中最小的传递单位就是 1 字节,通常使用 byte 来承载。咱们在通常的开发中确定会遇到这种在流中读取数据或字节数组转换成其余类型或在字节中读取相应位的数据等等业务场景,好比网络传输,蓝牙设备或物联网设备交互的场景,可能都会遇到。我举两个高位在前,低位在后的例子,这类操做通常都是使用位运算来实现。你们在业务中遇到其余的场景随机应变便可。

byte 与 char 的转换(高位在前,低位在后)

char c1 = '中'; // 二进制 0100111000101101 UTF-8 编码为 ’中‘

byte[] bytes = new byte[2];
bytes[0] = (byte) ((c1 >> 8) & 0xff); // 01001110
bytes[1] = (byte) (c1 & 0xff); // 00101101

char c2 = '国'; // 二进制 0100111000101101 UTF-8 编码为 '国'
// 第一步先把 c2 的值清空,两种方式
// 1. 左移 16 位将 c2 清零
c2 = (char) (c2 << 16);

// 2. 无符号右移 16 位将 c2 清零
c2 = (char) (c2 >>> 16);

c2 = (char) (c2 | (bytes[0] & 0XFF)); // 将低八位赋值
c2 = (char) ((c2 << 8) | (bytes[1] & 0XFF)); // 左移八位,继续将低八位赋值

// c2 的值被改成 ’中‘
复制代码

byte 与 int 的转换(高位在前,低位在后)

int i1 = 1234567890; // 二进制 01001001 10010110 00000010 11010010
byte[] bytes = new byte[4];
bytes[0] = (byte) ((i1 >> 24) & 0xFF);
bytes[1] = (byte) ((i1 >> 16) & 0xFF);
bytes[2] = (byte) ((i1 >> 8) & 0xFF);
bytes[3] = (byte) (i1 & 0xFF);


int i2 = 0;
i2 = i2 | (bytes[0] & 0XFF);
i2 = (i2 << 8) | (bytes[1] & 0XFF);
i2 = (i2 << 8) | (bytes[2] & 0XFF);
i2 = (i2 << 8) | (bytes[3] & 0XFF);
复制代码

取 Int 中的其中几位

在咱们通常的物联网通讯中可能会在一个 short 值中把操做符和 data 都放进去。好比一个 short 是 2 字节。也就是 16 位,举个例子好比前四位表示操做符,中间8位表示数据,后四位表示校验位。

假设与设备通信中规定好收到两个字节。

// byte[] 转换成 short
short data = 0;
data = (short) (data | (bytes[0] & 0XFF));
data = (short) ((data << 8) | (bytes[1] & 0XFF)); 

//假设 data 十进制的值为 31766 ,二进制为 01111100 00010110
// 取得前四位操做符 operator 为 28672 二进制 0111 0000 0000 0000
short operator = (short) (data & 0xF000); // 0xF000:11110000 00000000

// 取得中间八位数据 data1 为 3088 二进制 0000 1100 0001 0000
short data1 = (short) (data & 0x0FF0); // 0x0FF0:00001111 11110000

// 取得后四位校验位 check 为 6 二进制 0000 0000 0000 0110
short check = (short) (data & 0x000F); // 0x000F:00000000 00001111

复制代码

高位,低位

假设有个二进制的值为 1001 0110。

高位是左边开始数,好比高四位就是 1001。

低位是右边开始数,好比低四位就是 0110。

小结

这一篇我讲的比较乱,可是魂并无散,讲的都是二进制层面的一些知识点,也许不是最经常使用的也不是最全面的,可是若是我这篇博客,你可以看明白能够受益不浅。

相关文章
相关标签/搜索