跳转至

深入理解计算机系统

信息的表示和处理

位向量

markdown 数学公式参考: https://www.jianshu.com/p/4460692eece4https://www.jianshu.com/p/8b6fc36035c0

原文:P36

位向量就是固定长度为 w、由01组成的串。 位向量的运算是布尔代数运算的扩展,可以被定义为参数的每个对应元素之间的运算。假设 a 和 b分别表示位向量\([a_{w-1}, a_{w-2}, ..., a_0 ]\)\([b_{w-1}, b_{w-2}, ..., b_0 ]\)。我们将\(a \And b\)也定义为一个长度为\(w\)的位向量,其中第\(i\)个元素等于\(a_i \And b_i, 0 \le i \lt w\)可以用类似的方式将 ~ , ! , ^ 扩展到位向量上。 位向量的一个妙用就是表示有限集合。我们可以用位向量\([a_{w-1}, a_{w-2}, ..., a_1, a_0 ]\)编码任何子集\(A \subset \{ 0, 1, ..., w - 1 \}\),其中\(a_i = 1 \iff i \in A\). 举个栗子,位向量\(a = [01101001]\)表示集合\(A = \{ 0, 3, 5, 6 \}\),而\(b = [01010101]\)表示集合\(B = \{ 0, 2, 4, 6 \}\)。 用这种编码集合的方法,布尔运算|&分别对应集合的并和交,而~对应集合的补运算。 还是用前面那个例子,运算\(A \And B \(得到位向量\)[01000001]\), 而\(A \And B = \{ 0, 6 \}\)

  • 也就是在这种规则下说 位运算 里面的\(a \And b\)对应 数学集合运算里面的交集(\(\cap\))。

  • 关于\(a = [01101001]\)代表集合\(A = \{ 0, 3, 5, 6 \}\), 即表示 a 集合中位置第 0346 位时为二进制的0,所以表示为集合A.

查资料之后我的理解:

  • X ^ Y 异或运算,有一个为真,但不同时为真,则结果为真,否则结果为假。
  • ~ X 取反运算,为假时结果为真,为真时结果为假。
  • x & Y 与运算,同时为真时结果取真,否则结果为假。
  • X | Y 或运算,有一个为真时结果取真,否则结果为假。

补码的取值方式: 0异或是对方,1异或是对方的补.

例子:

    X = 01101001  # 原字节序列
    Y = 11111111  # 全数字1
    Z = 00000000  # 全数字0

  ~ X = 10010110  # 取反(~)运算 补运算
X ^ Y = 10010110  # 异或1运算 X 的补
X ^ Z = 01101001  # 异或0运算 X 自己

习题 2.12 写出变量x的C语言表达式

对于下面的值,写出变量X的C语言表达式。你的代码应该对任何字长W大于等8都能工作。我们给出了当X=0x87654321以及w=32时表达式求值的结果,仅供参考。

  • A. x的最低有效字节,其他位均置为0。【0x00000021】.
  • B. 除了X的最低有效字节外,其他的位都取补,最低有效字节保持不变。【0x789ABC21】。
  • C. x的最低有效位设置为全1,其他字节都保持不变。【0x876543FF】。
#include<stdio.h>


void convert(unsigned int var)
{
    printf("0x%.2x", var);
    printf("\n");

    // A答案
    int a = var & 0xFF;

    printf("0x%.2x", a);
    printf("\n");

    // 校验 

    unsigned int b = 0;
    printf("0x%.2x", (~ b));
    printf("\n");

    // B答案

    // printf("0x%.2x", ((~ var) ));
    // printf("\n");
    // printf("0x%.2x", ((~ var) & 0xFF ));
    // printf("\n");
    // printf("0x%.2x", ((~ var) & 0xFF ) | var);
    // printf("\n");
    // printf("0x%.2x", ~(((~ var) & 0xFF ) | var));
    // printf("\n");
    // printf("0x%.2x", (~(((~ var) & 0xFF ) | var)) | (var & 0xFF));
    // printf("\n");

    // C答案
    printf("0x%.2x", ((~ var) ));
    printf("\n");
    printf("0x%.2x", ((~ var) & 0xFF ));
    printf("\n");
    printf("0x%.2x", ((~ var) & 0xFF ) ^ var);
    printf("\n");


    return 0;

}

int main()
{
 printf("**************************\n");
 printf("dotcpp.com\n");
 printf("**************************\n");

 convert(0x87654321);
 return 0;
}

输出结果

**************************
dotcpp.com
**************************
0x87654321
0x21
0xffffffff
0x789abcde
0xde
0x876543ff

确定大小整型的更多内容

P47

#include<stdio.h>
#include<stdint.h>
#include<inttypes.h>

int main()
{
 printf("**************************\n");
 printf("dotcpp.com\n");
 printf("**************************\n");


    printf("0x%.2x", (~ -1));
    printf("\n");

    // 宏定义在头文件 <stdint.h> 中 , 确定int类型和 uint类型的字节数,无歧义声明,以保证可移植性
    int32_t x = 23123123;  // 指定位数声明
    uint64_t y = 551241243123;  // 指定位数声明

    // PRId32 和 PRIu64的宏定义在<inttypes.h>中
    printf("x = %" PRId32 ", y = %" PRIu64 "\n", x, y);

    //小写字母输出 
    printf("x = 0x%032x" ", y = 0x%064x" "\n", x, y);

    //大写字母输出 
    printf("x = 0x%032X" ", y = 0x%064X" "\n", x, y);


 return 0;
}

最后更新: 2023年2月23日
创建日期: 2023年2月23日