计算机存储数字和字符的原理?¶
一、数字的存储¶
1. 整数:补码(Two's Complement)¶
计算机用补码存储有符号整数,目的是让加减法统一电路(减法变加法)。
| 真值 | 原码 | 反码 | 补码 |
|---|---|---|---|
| +1 | 0000 0001 |
0000 0001 |
0000 0001 |
| -1 | 1000 0001 |
1111 1110 |
1111 1111 |
| -128 | 无 | 无 | 1000 0000 |
规则:
- 正数:原码 = 反码 = 补码。
- 负数:补码 = 反码 + 1,最高位是符号位(0 正 1 负)。
- 8 位补码范围:-128 ~ 127,比原码多表示一个 -128。
2. 浮点数:IEEE 754¶
Java 的 float(32 位)和 double(64 位)遵循 IEEE 754:
例如 0.1 在 double 中不是精确值,所以 0.1 + 0.2 != 0.3。金融计算用 BigDecimal。
二、字符的存储¶
1. ASCII¶
1 字节,最高位为 0,只能表示 128 个字符(英文字母、数字、控制符)。
2. ISO-8859-1(Latin-1)¶
1 字节,最高位置 1,扩展到 256,覆盖西欧语言。
3. GBK / GB2312¶
中文编码,1~2 字节。GB2312 收录 6763 个汉字;GBK 扩展到 21886 个。
4. Unicode 与 UTF-8 / UTF-16 / UTF-32¶
- Unicode:为每个字符分配一个唯一码点(Code Point),如
中 = U+4E2D。 - 但 Unicode 只定义码点,不规定怎么存。UTF 是存储实现:
- UTF-8:变长 1~4 字节。ASCII 字符占 1 字节,中文通常 3 字节。互联网最常用。
- UTF-16:Java 内部
char用的编码,变长 2/4 字节(BMP 字符 2 字节,辅助平面 4 字节)。 - UTF-32:定长 4 字节。
5. Java 中的 char 与 String¶
char是 UTF-16 码元,2 字节,只能表示 BMP 字符。- 像 emoji(如 😀 U+1F600)需要两个 char(代理对)。
String.length()返回的是 char 数量,不是 Unicode 字符数;codePointCount()才是字符数。
乱码根因
乱码 = 编码与解码用了不同的字符集。解决:明确指定 UTF-8,不要依赖平台默认编码(new String(bytes) 在不同系统结果不同)。