C/C++ 语法教程(2)——数据存储与进制转换
Contents
数据存储与进制转换
数据存储
众所周知,计算机中都是以二进制存储数据,但是不同的类型有很多种不同的存储要求,所以存储格式也各不相同。
无符号整型
存储即为其二进制,比如 $8$ 位二进制数 $01101011$ 表示的就是十进制数 $107$。
故如果输入数据超过存储上限(也称为溢出),相当于对 $2^{\text{位数}}$ 取模。
有符号整型
与无符号整型的最大区别就是最高位(左数第一位)变成了符号位,$0$ 表示正数,$1$ 表示负数。
正数的后面若干位就是按二进制(也称为原码)存储,而负数则是按补码存储(反码 $+1$),所谓反码就是将除符号位的所有位取反($0$ 变 $1$,$1$ 变 $0$)。
比如 $-1$ 的 $8$ 位原码是 $10000001$,反码就是 $11111110$,补码就是 $11111111$。
特别地,$10000000$ 本来表示 $-0$,但实际用于表示 $-128$。(位数增加也同理)
而有符号整型的溢出相当于无符号型的大的那一半接到了负数这边,比如 $8$ 位时,$10000000$ 表示有符号整型的 $-128$,也表示无符号整型的 $128$,$11111111$ 表示有符号整型的 $-1$,也表示无符号整型的 $255$。
浮点型
浮点型的存储大概分为符号位、尾数和阶码(反正名字不用记住)。
符号位 $s = 0/1$ 代表正数或者负数($(-1)^s$)。
尾数 $M$ 是一个二进制小数,与科学计数法相似,可以认为是二进制的科学计数法,也就是说 $1 \le M < 2$。阶码 $E$ 代表 $2$ 的幂,跟科学计数法相似,但其存储方法与有符号整型也不同。最后浮点型的数值表示为 $V = (-1)^s \times M \times 2^E$。如果是单精度浮点数,也就是 $32$ 位二进制,一般开头 $1$ 位表示符号位,中间 $8$ 位表示阶码,最后 $23$ 位表示尾数(注意顺序跟前面不同)。如果是双精度浮点数,则是 $1 + 11 + 52$ 的模式。尾数部分因为小数点前的一位必定是 $1$,所以不存储,只保存小数点后面的若干位。阶码先换算成二进制,然后整体平移,大概就是比如单精度 $8$ 位存储,就是加上 $127$ 再存储,也就是说 $4$ 实际存储为 $131$。特别地,当 $E$ 全为 $0$ 时,用于表示 $0$ 或者特别接近 $0$ 的数;当 $E$ 全为 $1$ 时,且 $M$ 全为 $0$,用于表示(正负)无穷大;当 $E$ 全为 $1$ 时,但 $M$ 不全为 $0$,用于表示不是一个数($NaN$),常见于被零(整型)除,负数开放等错误操作。
进制转换
$q$ 进制转成十进制
初始为 $0$,不断地乘 $q$ 加上这一位的数,记得到其十进制。
十进制转成 $q$ 进制
不断除 $q$,然后余数从前到后即为 $q$ 进制的位从低到高。(应该都好懂)
特殊的进制转换
比如二进制与十六进制,就可以将二进制按 $4$ 位分组,然后对应十六进制的一位。
C/C++ 中的进制转换
printf("%05o\n",35); //按八进制格式输出,保留5位高位补零
printf("%03d\n",35); //按十进制格式输出,保留3位高位补零
printf("%05x\n",35); //按十六进制格式输出,保留5位高位补零
#include <bitset>
#include<iostream>
using namespace std;
int main()
{
cout << "35的8进制:" << std::oct << 35<< endl;
cout << "35的10进制:" << std::dec << 35 << endl;
cout << "35的16进制:" << std::hex << 35 << endl;
cout << "35的2进制: " << bitset<8>(35) << endl; //<8>:表示保留8位输出
return 0;
}
除此之外还有 itoa
函数,大家可以自行研究。
No Comments