Golang 基础(十六)进制与编码

Overview

  • 进制
  • 单位
  • ASCII
  • Unicode
  • UTF-8

Description

1)进制

满N进1

二进制八进制十进制十六进制
0001
1112
10223
11334
100445
101556
110667
111778
10001089
1001119a
10101210b
10111311c
11001412d
11011513e
11101614f
1111171510
10000201611
10001211712
............

2)单位

计算机中底层处理的是二进制11011011    00110101类似的组合

位(b),一个二进制的位置

字节(byte):8位为一个字节

千字节(KB):1024个字节 = 1024 * 8 位

兆字节(MB):1024个千字节 = 1024 * 1024 字节 = 1024 * 1024 * 8

...

3) ASCII

DECOCTHEXBIN缩写/符号HTML实体描述
00000000000000NUL�Null char (空字符)
10010100000001SOHStart of Heading (标题开始)
20020200000010STXStart of Text (正文开始)
30030300000011ETXEnd of Text (正文结束)
.....................
1261767E01111110~~Equivalency sign (tilde)
1271777F01111111Delete

ASCII是早期计算机兴起的时候生产的一个编码表(American Standard Code for Information Interchange),是用于电子通信的7位编码系统,一共0-127个字节,虽然可以表示为8位,但是ASCII字符集只使用了7位来表示128个字符,因此最高位是01111111。

但早期的这个ASCII对应关系表并不足与满足当前社会所需的所有内容,比如汉字就无法表示,因此衍生了Unicode

4)Unicode

Unicode是万国码,基本上覆盖了全球所用的所有字符

Unicode有两种表示规则

  • UCS2: 是早期的一个表示规则,用16位来表示所有的字符,8位一个字节,也就是2个字节表示所有的字符,共2*16=65535个字节,但也不足以满足当今社会所有的情况,于是衍生除了UCS4
  • UCS4: 用32位来表示所有的字符,8位一个字节,也就是4个字节表示所有的字符,共2*32=4294967296个字符

UCS2可以兼容ASCII,UCS4可以兼容UCS2和ASCII

ASCII 是0-127个字节:

ASCII
00000000
01111111

Unicode的UCS2来表示ASCII是

UCS2
00000000 00000000兼容ASCII的0-127个字节
00000000 01111111
表示其他字符
11111111 11111111

Unicode的UCS4来表示ASCII和UCS2是

UCS4
00000000 00000000 00000000 00000000

兼容ASCII的0-127个字节

也意味着兼容UCS2的一部分字节

00000000 00000000 00000000 01111111
兼容UCS2剩余的字节
00000000 00000000 11111111 11111111
表示其他字符
11111111 11111111 11111111 11111111

虽然Unicode的UCS4覆盖面更广,但如果我所使用的字符在ASCII码中就可以找到,比如00000001,那么我使用ASCII就只使用1个字节,而Unicode的UCS2就需要用到2个字节,00000000 00000001,用UCS4就需要用到4个字节,00000000 00000000 00000000 00000001,所以在性能和存储上来说,此刻我肯定是直接使用ASCII来表示更好,那么我如何在使用的时候是找ASCII还是UCS2或者UCS4呢,那么如何解决这种问题避免浪费计算机资源呢?于是就衍生了UTF-8

5)码点

先了解概念:

在Unicode字符集中是通过码点找到对应字符的

在Unicode字符集中,码点是十六进制存在的

在Golang中,如果获取码点,则获取的默认是十进制显示的

我们有了码点,就可以通过UTF-8编码找到对应的码位范围,然后通过转换模板进行转换找到对应的字符,所以说UTF-8是可变长度的字符编码方式

以下介绍UTF-8

6)UTF-8

UTF-8编码是用于将Unicode字符集的码点编码为字节序列,以便在计算机中存储和传输

模板序号码位范围(十六进制)转换模板范围
10000  - 007F0xxxxxxxrunes 0-127(ASCII)
20080  - 07FF110xxxxx 10xxxxxx128-2047(values <128 unused)
30800  - FFFF1110xxxx 10xxxxxx 10xxxxxx2048-65535(values <2048 unused)
410000 - 10FFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx65536-0x10ffff(other values unused)

规律

0-127字节的二进制是以0开头

128-2047字节的二进制是110开头

2048-65536字节的二进制是1110开头

65535以上字节的二进制是1110开头

模板查找:

1)“A",使用rune获取"A"的十六进制码点,是41,在码位范围0000  - 007F,是第一个模板,那么转换模板就是0xxxxxxx

package main

import (
	"fmt"
	"strconv"
)

func main() {
	v1 := "A"
	DEC := []rune(v1)
	fmt.Println("使用Rune获取的十进制码点是:", DEC)
	HEX := strconv.FormatInt(int64(DEC[0]), 16)
	fmt.Println("将十进制的码点转换位十六进制是:", HEX)
}

2)“ǣ”,使用rune获取“ǣ”的十六进制码点,是1e3,在码位范围0080  - 07FF,是第二个模板,那么转换模板就是110xxxxx 10xxxxxx

package main

import (
	"fmt"
	"strconv"
)

func main() {
	v1 := "ǣ"
	DEC := []rune(v1)
	fmt.Println("使用Rune获取的十进制码点是:", DEC)
	HEX := strconv.FormatInt(int64(DEC[0]), 16)
	fmt.Println("将十进制的码点转换位十六进制是:", HEX)
}

3)“国”,使用rune获取"国"的十六进制码点,是56fd,在码位范围0800  - FFFF,是第三个模板,那么转换模板就是1110xxxx 10xxxxxx 10xxxxxx

package main

import (
	"fmt"
	"strconv"
)

func main() {
	v1 := "国"
	DEC := []rune(v1)
	fmt.Println("使用Rune获取的十进制码点是:", DEC)
	HEX := strconv.FormatInt(int64(DEC[0]), 16)
	fmt.Println("将十进制的码点转换位十六进制是:", HEX)
}

对”国“进行编码解释:

编码填充:

进行UTF-8编码填充,“国”的十六进制是56fd,将56fd对应的二进制输出:

十六进制56fd
二进制10111011111101

也就是0101 0110 1111 1101

填充模板1110xxxx 10xxxxxx 10xxxxxx

所以UTF-8编码点位就是11100101 10011011 10111101

代码验证:

将码点转换位十进制的字节后,使用byte来查看是否最终是”国“

package main

import (
	"fmt"
	"strconv"
)

func main() {
	DEC1, _ := strconv.ParseInt("11100101", 2, 64)
	DEC2, _ := strconv.ParseInt("10011011", 2, 64)
	DEC3, _ := strconv.ParseInt("10111101", 2, 64)
	fmt.Println(DEC1, DEC2, DEC3)
}

可以看到将UTF-8编码的二进制码点转换为十进制后是229 155 189,使用byte来将十进制的字节转换为字符:

package main

import (
	"fmt"
	"strconv"
)

func main() {
	DEC1, _ := strconv.ParseInt("11100101", 2, 64)
	DEC2, _ := strconv.ParseInt("10011011", 2, 64)
	DEC3, _ := strconv.ParseInt("10111101", 2, 64)
	fmt.Println(DEC1, DEC2, DEC3)
	result := []byte{229, 155, 189}
	fmt.Println(string(result))
}

可以看到结果是”国“

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值