前言
数据类型 字节的使用
正文
一,布尔代数表示
1, 位运算
a = [0110], b = [1100]
1.1 &
0110
&1100
0100
1.2 |
0110
|1100
1110
1.3 ^
0110
^1100
1010
1.4 ~
~1100
0011
2, 分配侓
-
布尔运算侓 & 对 的有分配侓 -
布尔运算侓 对 & 的有分配侓
a * (b + c) = (a + b) + (a + c) ==> a & (a | b) = (a & b) | (a & c)
位向量一个很有用的应用就是表示有限集合。我们可以用位向量 [$a_{w-1}$, $a_{w-2}$ …, $a_0$]编码任何子集A$\subseteq$ {0, 1, …, w - 1}, 其中 $a_i$ = 1 当且仅当 $i\in$ A 。 例如(记住是把$a_{w - 1}$ 写在左边, 而将 $a_0$ 写在右边。), 位向量 a = [01101001]表示集合 A = {0, 3, 5, 6}, 而 b = [01010101] 表示集合 B = {0, 2, 4, 6}。 使用这种编码集合的方法, 布尔运算 | 和 & 分别对应于集合的并和交, 而 ~ 对应于于集合的补。
还是分配侓a&b得到位向量[01000001], 而 A $\cap$ B = {0, 6}
3, 运用位级计算
void inplace_swap(int *x, int *y)
{
*y = *x ^ *y;
*x = *x ^ *y;
*y = *x ^ *y;
}
- 交换数组中第一元素和最后一个元素
void reverse_array(int a[], int cnt)
{
int first, last;
for (first = 0, last = cnt - 1; first <= last; ++first, --last)
{
inplace_swam(&a[first], &a[last]);
}
}
上面代码有一个问题 就是奇数时会错误
cnt = 2k - 1
4, 移位运算
位的表示 A = [$X_{w - 1}$, $X_{w - 2}$, … , $X0$]
1, 左移(«)
A « k $\Longrightarrow$ [$X_{w - k - 1}$, $X_{w - k - 2}$, … , $X0$, 0, 0, $0_k$]
2, 右(») –有点奇葩
分为两种情况:
1. 逻辑右移 2. 算术右移- 逻辑右移
右移在左端补k个0
A » k $\Longrightarrow$ [0, 0, 0, $0k$, $X{w - 1}$, $X_{w - 2}$, … , $X0$]
- 算术右移
算术右移在左端补k个最高位有效的值
A » k $\Longrightarrow$ [$X_{w - 1}$, $X_{w - 1}$, …, $X_{w - 1}$, $X_{w - 1}$, $X_{w - 2}$, … , $X0$]
看一下实例
操作 | 值 |
---|---|
参数 | [0110 0011] [1001 0101] |
x « 4 | [0011 0000] [0000 0101] |
x » 4 (逻辑右移) | [$\mathsf{0000}$ 0110] [$\mathsf{0000}$ 1001] |
x » 4 (算术右移) | [$\mathsf{0000}$ 0110] [$\mathsf{1111}$ 1001] |
5.1,整数表示
描述位来编码整数的两种不同的方式:
一种只能表示非负数, 二别一种能够表示负数, 零和整数下面是一些术语
符号 | 类型 | 含义 |
---|---|---|
$B2T_w$ | 函数 | 二进制转补码 |
$B2U_w$ | 函数 | 二进制转无符号数 |
$U2B_w$ | 函数 | 无符号数转换二进制 |
$U2T_w$ | 函数 | 无符号数转换补码 |
$T2B_w$ | 函数 | 补码转二进制 |
$T2U_w$ | 函数 | 补码转无符号数 |
$TMin_w$ | 常数 | 最小补码值 |
$TMax_w$ | 常数 | 最大补码值 |
$UMax_w$ | 常数 | 最大无符号数 |
$+_w^t$ | 操作 | 补码加法 |
$+_w^u$ | 操作 | 无符号数加法 |
$*_w^t$ | 操作 | 补码乘法 |
$*_w^u$ | 操作 | 无符号数乘法 |
$-_w^t$ | 操作 | 补码取反 |
$-_w^u$ | 操作 | 无符号数取反 |
5.2 整数数据类型
32位机器
C数据类型 | 最小值 | 最大值 |
---|---|---|
[signed] char | -128 | 127 |
unsigned char | 0 | 255 |
short | -32768 | 32767 |
unsigned short | 0 | 65535 |
int | -2147483648 | 2147483647 |
unsigned int | 0 | 4294867295 |
long | -2147483648 | 2147483647 |
unsigned long | 0 | 4294967295 |
int32_t | -2147483648 | 2147483647 |
uint32_t | 0 | 4294867295 |
int64_t | -9224472036854775808 | 9224472036854775807 |
uint64_t | 0 | 18446744073709551615 |
C/C++都是支持有符号(默认)和无符号数。 Java只支持有符号数
5.3 无符号数的编码
有一个整数类型是有w位,我们可以将位向量写成 $\vec X$, 表示整个向量, 或者[$X_{w - 1}$, $X_{w - 2}$, … , $X_0$], 表示向量中每一位。把$\vec X$ 看做一个二进制表示的数, 就获取了 $\vec X$ 的表示。在整个编码中国, 每个位 $X_i$ 都取值为0或1, 我们使用一个函数 $B2U_w$
原理: 无符号数编码的定义
对向量 $\vec X$ $\Longrightarrow$ [$x_{w - 1}$, $x_{w - 2}$, …, $X_0$]
$B2U_w$($\vec x$) == $\sum_{i = 0}^{w - 1}{x_i}{2^i}$
下面是几种情况
$B2U_4$([0001]) = 0 * $2^3$ + 0 * $2^2$ + 0 * $2^1$ + 1 * $2^0$ = 0 + 0 + 0 + 1 = 1
$B2U_4$([0101]) = 0 * $2^3$ + 1 * $2^2$ + 0 * $2^1$ + 1 * $2^0$ = 0 + 4 + 0 + 1 = 5
$B2U_4$([1011]) = 1 * $2^3$ + 0 * $2^2$ + 1 * $2^1$ + 1 * $2^0$ = 8 + 0 + 2 + 1 = 11
$B2U_4$([1111]) = 1 * $2^3$ + 1 * $2^2$ + 1 * $2^1$ + 1 * $2^0$ = 8 + 0 + 2 + 1 = 15
结语
最后总结一下:
在使用数据类型时要 注意数据类型 C++中有解释类型[reinterpret_cast < new_type > ( expression )]