一、实型(浮点型)
浮点数能够表示带小数部分的数值,如:2.5,3.14,122.22等
计算机将这样的值分成两部分存储,一部分表示值,另一部分用于对值进行放大或者缩小。如数值34.125可以看作0.34125(基准值)和100(缩放因子)。缩放因子的作用是移动小数点的位置,术语浮点因此而得名。
C++内部表示浮点数的方法与此相同,只不过它基于的是二进制,因此缩放因子是2的幂,不是10的幂。浮点数可以表示非常大的值和非常小的值,他们的内部表示方法与整数有天壤之别。
实型分为:单精度浮点数(float 4字节),双精度浮点数(double 8字节)
实型常量
不以f结尾的实型常量为double类型,如:3.14
以f结尾的实行常量为float类型,如:3.14f
指数形式:123e3代表123*10的三次方,123e-3
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << 3.14 << endl;
cout << sizeof(3.14) << endl; // double类型为8个字节
cout << 3.14f << endl;
cout << sizeof(3.14f) << endl; // float类型为4个字节
cout << 0.314e1 << endl;
cout << 314e-2 << endl;
return 0;
}
实型变量
单精度实型变量:float,占4字节,以f结尾的实型常量初始化
float f = 0.0f;
双精度实型变量:double,占8字节,不以f结尾的实型常量初始化
double d = 0.0;
二、有符号数和无符号数
有符号数
数据二进制的最高位为符号位,其他位为数据位。
最高位为1,表示负数
最高位为0,表示正数
以1字节为例:xddd dddd
1111 1111 -127
1000 0000 -0(看作-128)
0000 0000 +0
0111 1111 +127
无符号数
没有符号位,所有二进制位都是数据位
0000 0000 0
1111 1111 255
定义有符号变量
// 方式一:默认方式(推荐)
int num; // num为有符号数
// 方式二:使用关键字signed显示说明
signed int num;
定义无符号变量
unsigned int num; //定义无符号数
三、进制间的转换
二进制:0—1,以0b开头,bitset<8> 输出
八进制:0—7,以0开头,oct 输出
十进制:0—9,cout默认以十进制输出
十六进制:0—9 a—f,以0x开头,hex 输出,不区分正负数
n进制:0—n-1
十进值转二进制,八进制,十六进制
求商取余法
例:123 转成二进制 0b0111 1011
例:123 转成八进制 0173
例:123转成16进制 0x7b
其他进制转十进制
位次幂法
将n进制数xyz转成十进制:x*n^2+y*n^1+z*n^0
例:1100 0011 转成十进制 195
例:0123 转成十进制 83
例:0x12 转成十进制 18
二进制转八进制
从右往左,每3位二进制 对应 1位八进制
101 1010 011 011 010 3 3 2
二进制转十六进制
从右往左,每4位二进制 对应 1位十六进制
101 1010 1101 1010 d a
八进制转二进制
1位八进制 对应 3位二进制
332 011 011 010
十六进制转二进制
1位十六进制 对应 4位二进制
da 1101 1010
C++实现进制转换
dec,oct,hex会改变后面cout输出数字的进制
#include <iostream>
#include <bitset>
using namespace std;
int main(int argc, char *argv[])
{
int num=100;
cout << num << "的二进制为:" << bitset<8>(num) << endl;
cout << num << "的八进制为:" << oct << num << endl;
cout << "num现在的值为:" << num << endl; // num的值从100变成了八进制下的144
return 0;
}
#include <iostream>
#include <bitset>
using namespace std;
int main(int argc, char *argv[])
{
int num=100;
cout << num << "的二进制为:" << bitset<8>(num) << endl;
cout << num << "的八进制为:" << oct << num << endl;
cout << dec << num << "的十六进制为:" << hex << num << endl;
cout << dec << num << "的十进制为:" << num << endl;
return 0;
}
四、源码,反码,补码
计算机存储的是数据的补码
原码:计算机中对数字的二进制定点表示方法
123 原码 0111 1011
无符号数:补码 = 反码 = 原码
123 原码 0111 1011
123 反码 0111 1011
123 补码 0111 1011
有符号数:
正数:补码 = 反码 = 原码
+123 原码 0111 1011
+123 反码 0111 1011
+123 补码 0111 1011
负数:反码 = 原码符号位不变,其他位按位取反
补码 = 反码 + 1
-123 原码 1111 1011
-123 反码 1000 0100
-123 补码 1000 0101
补码的意义
1. 统一了0的编码
+0的补码:0000 0000
-0的原码:1000 0000
-0的反码:1111 1111
-0的补码:0000 0000
2. 将减法运算变成了加法运算
原码计算:10-6
10: 0000 1010
-6: 1000 0110
-------------------
1001 0000 ------> 16 结果有问题
补码计算:10-6
10: 0000 1010
-6: 1111 1010
-------------------
0000 0100 ------> 4 结果正确
五、对数据的存
负数在计算以补码的方式存储
非负数在计算机以原码的方式存储
八进制数以原码的方式存储
十六进制数以原码的方式存储
以十六进制查看内存数据存储情况
六、对数据的取
如果是对无符号变量进行取值,输出内存的原样数据
如果是对有符号变量进行取值,系统会去看内存的最高位,如果最高位为0表明正数,内存原样输出;如果最高位为1表明负数,将内存数据求补码(得到原码)输出
七、其他关键词
1. const修饰普通变量
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
// const修饰num为只读变量,只能被初始化,不能被赋值
const int num = 100; // 初始化时不赋值会报错
// num = 100; 后面赋值也会报错
return 0;
}
如果以常量初始化const修饰的只读变量,那么只读变量的值事先存放在“符号常量表中”,不会立即给num开辟空间
当对num取地址时,系统才会为num开辟空间
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
const int num = 100; // num,100存放在符号常量表中
int *p = (int *)# // 为num开辟空间,*p指向空间内容
cout << "*p = " << *p << endl; // *p指向的空间内容为num的值,100
cout << "num = " << num << endl; // num存在于符号常量表中,100
*p = 200; // 修改为num开辟的空间的值
cout << "*p = " << *p << endl; // *p指向的空间内容为修改后的值,200
cout << "num = " << num << endl; // num仍然存在于符号常量表中,值不变,100
return 0;
}
如果以变量初始化const修饰的只读变量,那么只读变量会立即开辟空间(没有符号常量表)
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int data = 200; // 定义一个变量
const int num = data; // 用变量初始化const修饰的只读变量,会立即开辟空间
int *p = (int *)# // 定义一个指向为num开辟的空间的内容的指针
cout << "*p = " << *p << endl; // *p指向的空间的内容为num的值,200
cout << "num = " << num << endl; // num存在开辟的空间中,200
*p = 100; // 修改为num开辟的空间的值
cout << "*p = " << *p << endl; // *p指向的空间内容为修改后的值,100
cout << "num = " << num << endl; // num存在的空间的值被改变,100
return 0;
}
const修饰自定义类型变量会立即开辟空间(没有符号常量表)
2. register修饰寄存器变量
如果变量被高频使用,会自动将变量存储在寄存器中,目的:提高访问效率
如果用户想将变量直接存入寄存器中可以加register修饰
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
register int data = 10; // data不会被放入内存中,而是放在cpu的寄存器中
// 尽量不要对寄存器变量取地址
// register修饰的变量只是尽量放入寄存器中(寄存器数量有限)
return 0;
}
3. volatile关键字
强制访问内存,防止编译器优化
volatile int data; // 对data的访问必须从内存访问
4. sizeof测量类型的大小
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << sizeof('a') << endl; // 1B
cout << sizeof("a") << endl; // 2B
cout << sizeof(10) << endl; // 4B
cout << sizeof(3.14) << endl; // 8B
cout << sizeof(char) << endl; // 1B
cout << sizeof(long) << endl; // 4B
cout << sizeof(short) << endl; // 2B
cout << sizeof(float) << endl; // 4B
cout << sizeof(double) << endl; // 8B
return 0;
}
5. typedef给已有的类型重新取个别名
不能创建新类型
将长且复杂的类型名去一个短小的名称
typedef作用的步骤:
1. 先用已有的类型定义一个普通的变量
2. 用别名替换变量名
3. 在整个表达式最前方加typedef
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
typedef int INT32; //INT32就是int类型的别名
INT32 data = 10;
int num = 20; // 原有的类型仍然有效
cout << "INT32定义的数字为:" << data << endl;
cout << "int定义的数字为:" << num << endl;
return 0;
}
案例:给int arr[5] 取个别名
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
typedef int Myarray[5];
Myarray list = {1,2,3,4,5};
for(int i=0;i<5;i++)
{
cout << list[i] << ' ';
}
cout << endl;
return 0;
}