当前位置: 首页 > ai >正文

数据存储与运算

计算机中的数据存储与运算

输出地址后看不懂格式,为什么?


第一节:进制转换基础

✅ 常见进制:
  • 十进制(Decimal):日常使用的 0~9
  • 二进制(Binary):计算机底层使用,仅有 0 和 1
  • 八进制(Octal):0~7,早期用于嵌入式
  • 十六进制(Hex):09A~F(代表 0~15),常用于表示地址,为二进制的缩写等
✅ 为什么使用十六进制表示二进制?
  • 二进制太长不直观,容易出错
  • 1 个十六进制位 = 4 个二进制位(更简洁)
  • 举例:11111111 11111111 可以写成 0xFFFF
  • 程序员常用 0x 开头表示十六进制,方便调试与内存分析
✅ 转换示例:
十进制二进制十六进制
1010100xA
255111111110xFF
16100000x10

第二节:数据存储方式

✅ 什么是“位数”?
  • 位(bit):计算机的最小单位,0 或 1

  • 32 位系统:一个寄存器/地址一次最多处理 32 位数据,11111111 11111111 11111111 11111111 ,0xFFFFFFFF

  • 64 位系统:一次最多处理 64 位数据,以上例子的两倍

  • 位数决定:寻址能力、运算精度、可用内存(每个地址能存一个字节的内容)等

✅ 什么是“字节”?

  • 一字节等于8位,2^8,能存2的8次方大小的数据

常见存储范围

8 位2⁸ = 256256 个值0 ~ 255 或 -128 ~ 127
32 位2³² ≈ 42 亿42 亿个值0 ~ 4294967295 或 -2147483648 ~ 2147483647

16位 65536 -32768~32767

✅ 整型存储:
  • 占用固定字节数(如 int 通常 4 字节 = 32 位)

  • 按照补码方式存储(后面详细讲)

  • 二进制按位存储,例如:

    int a = 5; // 实际存储:00000000 00000000 00000000 00000101 32位系统下地址:0x00 00 00 05 64位同理
    
✅ 浮点型存储:(极为复杂不做了解)
  • 拆成三部分:符号位 + 指数位 + 尾数位(有效数字)
  • 单精度(float):32 位 = 1 + 8 + 23
  • 双精度(double):64 位 = 1 + 11 + 52
✅ 单精度 vs 双精度区别:(只需要知道是双倍精度,存储空间是双倍就行了)
属性float(单精度)double(双精度)
位数32 位64 位
精度约 7 位十进制约 15 位十进制
范围±3.4e38±1.8e308
占用内存4 字节8 字节

✅ 最通俗的一句话总结:(也不用学)

在浮点数中:

  • 尾数位 决定 “是什么数” (有效数字)
  • 指数位 决定 “它放在哪个大小范围” (缩放倍数)

字符型存储与 ASCII

✅ 字符 = 整数
  • 在底层,char 类型是 1 字节整数
  • 字符用整数存储,那么为什么知道是字符呢?对应表格
  • 字符 'A' 实际存储值为 65,对应 ASCII 编码表,0100 0001,0x41
✅ ASCII 表示例:
字符十进制二进制
'A'6501000001
'a'9701100001
'0'4800110000

✅ 为什么A和a差了32?

0x20

只需要记住大写A是65就记住全部

✅ 演示代码:
char c = 'A';
cout << (int)c << endl; // 输出 65
cout << (int)(c + 0x20) << endl;
cout << (c += 0x20) << endl;
cout << (c -= 0x20) << endl;

✅ 说明:字符本质上就是整数,赋值/比较时可作为数值使用。

ASCII码不过一个字节大小范围,0~255,如何记得下全世界数百上千万的符号?

不同的语言体系有不同的编码版本,

✅ 扩展:其他编码(中文/Unicode)
编码方式特点示例(字符“你”)
ASCII单字节,只支持英文不支持
GB2312/GBK汉字双字节编码0xC4E3
UTF-8可变长度编码,全球通用0xE4 0xBD 0xA0(3 字节)
Unicode/UTF-16固定宽度(2 字节)0x4F60
十六进制序列Windows-1252GBKUTF-8
0xBDB2½ (分数 1⁄2)汉字 “貢”非法²

✅ 总结

  • 数据在内存中以 二进制补码 的形式存储
  • 字符、整数、浮点数都有不同的存储结构
  • 编码方式影响符号处理,补码是主流方式
  • ASCII 编码将字符与整数绑定,字符可以看作数
  • 二进制运算是低级优化与嵌入式开发的基础
  • UTF-8/Unicode 等是现代字符集标准,支持多语言
  • 计算机内存是一个大快递仓库,每个字节有唯一编号(地址)
  • 数据在内存中必须分配“空间”(多少字节)
  • 不同类型变量占用空间不同,越大越精确,但浪费空间

第三节:编码方式(原码、反码、补码)

(为何要用补码,原理较为复杂,不要求掌握,只要求掌握计算补码)

计算机中负数存的不是原码,而是补码,便于计算机运算,(为什么)

✅ 有符号数(负数):
  • 最高位为符号位:0 代表正,1代表负,以四位数据的原码举例,1为0001,-1为1001
  • 正数用原码存储,讨论补码时,都是讨论负数
✅ 编码定义:
编码方式定义
原码符号位 + 绝对值(除去符号的值)
反码原码除符号位外取反
补码反码 + 1

总结就是,补码就是正数原码取反+1

-5的补码计算 -> 抛开第一位符号位 -> 5的二进制原码 -> 0101 -> 取反 -> 1010 -> +1 -> 1011

5的原码是0101,-5的补码为1011

✅ 原因、原理:

芯片底层进行加减法运算的时候,只使用加法模块,单独设计减法模块太复杂,那么减法用加法模块替代,如何替代?

以四位长度数据计算举例:5 - 1 = 5 + (2^4 - 1) - 2^4
1.此处2^4是一个4位长度的数据的最大范围 + 1
二进制表示为:0101 + (10000 - 0001)- 10000 = 0101 + 1111 - 10000

2.此处的1111也就是(10000 - 0001)的计算结果,但其实1111是0001取反+1的结果,而非真正执行了减法,意思就是用取反模块和加法模块在此处模拟出了减法模块,但此处还没有结束,我们继续计算,10100 - 10000,这一步又要如何减去呢?

3.前面提到过,这是一个4位长度的数据,所以会自动把最高的那一位给丢弃,也就达成了减去最高位的1的效果,最后的结果也就是0100也就是4,5 - 1 = 4,就完成了,全程没有使用减法模块

4.这便是计算补码的原因以及原理,所以负数都以补码的形式存储,运算的时候使用的是加法模块,原码和补码也就是通过取反+1互相转换,1的原码为0001,补码为1111,(10000 - 0001) = 1111,(10000 - 1111) = 0001

✅ 示例:以 8 位为例,表示 -5:
编码方式二进制表达
原码10000101
反码11111010
补码11111011 ✅
✅ 无符号数 unsigned 前缀 unsigned int 无符号整型 unsigned double 无符号浮点型
  • 全部位用于表示数值,不能表示负数
  • 例如 8 位无符号最大值为 255,0 ~ 255, 二进制 0000 0000 ~ 1111 1111
  • 带符号最大值为 127,最小为-128,也就是 0 ~ 127,-1 ~ -128
  • 二进制 0000 0000 ~ 0111 1111, 原码1000 0001 ~ 1111 1111,补码 1111 1111 ~ 1000 0001

第四节:二进制运算基础

✅ 常见运算符:
运算符含义示例(a = 5, b = 3)a = 0101, b = 0011
&按位与a & b = 1
|按位或a | b = 7
^按位异或a ^ b = 6
~取反~a = -6
<<左移a << 1 = 10
>>右移a >> 1 = 2
✅ 十进制类比:
运算符类似什么示例
&相当于“都满足”0101 & 0011 = 0001
|相当于“至少一个满足”0101 | 0011 = 0111
^相当于“不同为真”0101 ^ 0011 = 0110
~相当于“取反”~00000101 = 11111010
<<乘 2^n101 << 1 = 1010
>>除 2^n101 >> 1 = 2
✅ 运算例题:
  1. 7 & 3 = 0111 & 0011 = 0011 = 3
  2. 4 | 2 = 0100 | 0010 = 0110 = 6
  3. 5 ^ 1 = 0101 ^ 0001 = 0100 = 4
  4. ~1 = 11111110(此处取反后为补码,补码无法一眼看出大小,通过反码+1还原成原码,可以看出实际大小)
  5. 2 << 2 = 88 >> 1 = 4

✅ 位运算和普通数学运算之间的关系概览

位运算符数学意义示例对应数学操作
<< n左移 n 位a << n = a × 2ⁿ快速乘法(×2ⁿ)
>> n右移 n 位a >> n = a ÷ 2ⁿ(整数除法)快速除法(÷2ⁿ,舍去余数)
^按位异或(相同为0)a ^ b二进制的“无进位加法”
~按位取反~a-a - 1 等价

✅ 一、<< 左移:等于乘以 2 的 n 次方

a << n ≡ a × 2

示例:

3 << 2 = 3 × 4 = 12

二进制表示:

3 = 00000011  
左移 2 位 → 00001100 = 12

✅ 二、>> 右移:等于除以 2 的 n 次方(向下取整)

a >> n ≡ a ÷ 2ⁿ(向下取整)

示例:

19 >> 2 = 19 ÷ 4 = 4 (舍去余数)

✅ 三、^ 按位异或:相同为 0,不同为 1(无进位加法)

a = 1101  
b = 1011  
→ a ^ b = 0110  此处第一位和第四位没有进位

🔁 **异或的一大作用:**用于交换两个数

a ^ a = 0
a ^ 0 = a

常用于:

  • 交换两个数不用临时变量:(原理,能理解最好,但并不常用到,可以自己推一遍)
a ^= b;
b ^= a;
a ^= b;
a = 1101  
b = 1011  
a ^= b; a  1101  b  1011  -> a  0110
b ^= a; a  0110  b  1011  -> b  1101
a ^= b; a  0110  b  1101  -> a  1011A 1101B 1011C 0110标记计算法:C就是A和B异或计算得出的标记位,每一位的01都是一个标记不同为0,相同为1,与0异或维持不变,与1异或反转自身C第一、四位的0表示,AB的第一、四位相同,无论是1还是0,异或运算0以后还是自身C第二、三位的1表示,AB的第二、三位不同,无论是1还是0,异或运算1以后都要反转,因为位不同,反转之后只能是对方的位

🧠 建议:手动练习补码运算、位操作、小型进制转换程序,有助于理解底层原理。

http://www.xdnf.cn/news/10359.html

相关文章:

  • 多端学习方案起笔
  • Linux基础 文件描述符,重定向及缓冲区理解
  • MCU如何从向量表到中断服务
  • Goreplay最新版本的安装和简单使用
  • asyncpg - Python异步PostgreSQL客户端库
  • 4、获取树莓派温度
  • Jenkins:自动化流水线的基石,开启 DevOps 新时代
  • 【Linux网络编程】数据链路层
  • 6个月Python学习计划 Day 11 - 列表推导式、内置函数进阶、模块封装实战
  • 让编程更智能高效:探索Claude Code工具的强大功能
  • Qt源码分析:QDataStream
  • 多模态大语言模型arxiv论文略读(103)
  • 功能丰富的PDF处理免费软件推荐
  • 设计模式——命令设计模式(行为型)
  • while循环判断数字位数
  • Axure组件即拖即用:垂直折叠菜单(动态展开/收回交互)
  • day16 leetcode-hot100-31(链表10)
  • DAY40 训练和测试
  • Vue 核心技术与实战智慧商城项目Day08-10
  • 麦克风和电脑内播放声音实时识别转文字软件FunASR整合包V5下载
  • 关于langchain使用API加载model的方式
  • Java并发编程实战 Day 3:volatile关键字与内存可见性
  • C++学习-入门到精通【12】文件处理
  • 工作流引擎-09-XState 是一个 JavaScript 和 TypeScript 的状态管理库,它使用状态机和状态图来建模逻辑。
  • Hilbert曲线
  • 在Flutter中定义全局对象(如$http)而不需要import
  • vue3: baidusubway using typescript
  • MYOJ_4149:(洛谷P1002)[NOIP 2002 普及组] 过河卒(坐标型DP)
  • 在Mathematica中可视化Root和Log函数
  • 实现RabbitMQ多节点集群搭建