golang 计算机补码、反码、补码、进制相互转换
对于整数,有四种表示方式:
1)、二进制:0,1 ,满 2 进 1。在 golang 中,不能直接使用二进制来表示一个整数,它沿用了 c 的特点。
2)、十进制:0-9 ,满 10 进 1。
3)、八进制:0-7 ,满 8 进 1. 以数字 0 开头表示。
4)、十六进制:0-9 及 A-F,满 16 进 1. 以 0x 或 0X 开头表示。此处的 A-F 不区分大小写
简单的格式化进制输出的示例
package main
import "fmt"
func main() {
// 十进制格式化为二进制
var i int = 5
fmt.Printf("%b\n", i)
// 八进制格式化为十进制
var j int = 011
fmt.Println("j=", j)
// 十六进制格式化为十进制
var k int = 0x11
fmt.Println("k=", k)
}
1、二进制、八进制、十六进制转为十进制
1.1、二进制转为十进制
例如:1011
手动换算:1 * 2^(4-1) + 0 * 2^(3-1) + 1 * 2^(2-1) + 1 * 2^(1-1)
8 + 0 + 2 + 1 = 11
代码运算:
ret, _ := strconv.ParseInt("1011", 2, 64) // 11
1.2、八进制转为十进制
例如:23
手动换算:2 * 8^(2-1) + 3 * 8^(1-1)
16 + 3 = 19
代码运算:
ret, _ := strconv.ParseInt("23", 8, 64) // 19
1.3、十六进制转为十进制
例如:23
手动换算:2 * 16^(2-1) + 3 * 16^(1-1)
32 + 3 = 35
代码运算:
ret, _ := strconv.ParseInt("23", 16, 64) // 35
2、十进制转为二进制、八进制、十六进制
2.1、十进制转为二进制
例如:56
手动换算: 余数,从下往上取值
2 | 56 ... 0
2 | 28 ... 0
2 | 14 ... 0
2 | 7 ... 1
2 | 3 ... 1
1 ... 1
111000
代码运算:
ret := strconv.FormatInt(56, 2) // 111000
2.2、十进制转为八进制
例如:56
手动换算: 余数,从下往上取值
8 | 56 ... 0
7 ... 7 //小于8,从下往上取值
70
代码运算:
ret := strconv.FormatInt(56, 8) // 70
2.3、十进制转为十六进制
例如:56
手动换算: 余数,从下往上取值
16 | 56 ... 8
3 ... 3 //小于16,从下往上取值
38
代码运算:
ret := strconv.FormatInt(56, 16) // 38
3、二进制转为八进制、十进制、十六进制
3.1、二进制转为八进制
例如: 11010101
手动换算:每取3位,进行 4 2 1 按位的运算
421=3 421=2 421=5
011 010 101
结果:0325
代码运算:
// 2进制转为10进制
base_10, _ := strconv.ParseInt("11010101", 2, 64) //213
// 10进制转为8进制
ret := fmt.Sprintf("%o", base_10) //325
fmt.Println(ret)
3.2、二进制转为十六进制
例如: 11010101
手动换算:每取4位,进行 8 4 2 1 按位的运算
8421=13 8421=5
1101 0101
D5
代码运算:
// 2进制转为10进制
base_10, _ := strconv.ParseInt("11010101", 2, 64) //213
// 10进制转为16进制
ret := fmt.Sprintf("%X", base_10) //D5
fmt.Println(ret)
3.3、二进制转为十进制
例如: 11010101
手动换算:
// 先转为16进制
每取4位,进行 8 4 2 1 按位的运算
8421=13 8421=5
1101 0101
D5
// 然后再由十六进制转为10进制
D * (16^2-1) + 5 * (16^1-1)
13*16 + 5 = 213
代码运算:
// 2进制转为10进制
base_10, _ := strconv.ParseInt("11010101", 2, 64) //213
4、八进制、十进制、十六进制转为二进制
4.1、八进制为二进制
例如: 123
手动换算:采用:421,按位换算
421 421 421
001 010 011
1 2 3
-----------------------
123 ==> 001010011
代码运算:
// 8进制转为2进制
ret := fmt.Sprintf("%b", 0123)
fmt.Println(ret) //1010011
4.2、十进制为二进制
例如: 123
手动换算:取2,取余数,从下往上取值
2 | 123 ... 1
2 | 61 ... 1
2 | 30 ... 0
2 | 15 ... 1
2 | 7 ... 1
2 | 3 ... 1
2 | 1 ... 1
---------------------
1111011
代码运算:
// 10进制转为2进制
ret := fmt.Sprintf("%b", 123) // 1111011
fmt.Println(ret)
4.3、十六进制为二进制
例如: 123
手动换算:取4位,采用:8421,按位换算
8421 8421 8421
0001 0010 0011
1 2 3
-----------------------
123 ==> 000100100011
代码运算:
// 16进制转为2进制
ret := fmt.Sprintf("%b", 0x123)
fmt.Println(ret) //100100011
5、原码、反码、补码
1、二进制最高位是符号位:0表示正数,1表示负数
2、正数的原码、反码、补码都是一样
3、负数的反码=原码符号位不变,其它位取反(0->1,1->0)
4、负数的补码=反码+1
5、0的反码、补码都是0
6、在计算机运算的时候都是以补码的方式来运算
5.1、负数的&或|或^的运算示例
2 & -3
原码 反码 补码
2 => 0000 0010 0000 0010 0000 0010
-3 => 1000 0011 1111 1100 1111 1101
------------------------------------------------
0000 0000
2 | -3
原码 反码 补码
2 => 0000 0010 0000 0010 0000 0010
-3 => 1000 0011 1111 1100 1111 1101
------------------------------------------------
1111 1111
反推为原码:
原码 补码 运算结果
1000 0001 1111 1110 1111 1111
结果为: -1
2 ^ -2
原码 反码 补码
2 => 0000 0010 0000 0010 0000 0010
-2 => 1000 0010 1111 1101 1111 1110
------------------------------------------------
1111 1100
反推为原码:
反码 补码 运算结果
1000 0100 1111 1011 1111 1100
结果为: -4