任务一:总结归纳计算机编程中的各种数据类型,其表示形式和计算方法。重点关注类型转换、数值溢出和移位等操作。
以C语言为例,C语言允许使用的数据类型包括:基本类型、构造类型、指针类型、空类型
(1) 基本类型:不可分割的最基本的数据类型,包括整型 (short int long) 浮点型 (float double) 字符型 (char) 逻辑型 (boolean(只可取true false)) 其中每种整型与字符型都有有符号版(signed) 和无符号版(unsigned)
(2) 构造类型:由基本类型构造,包括数组、结构体、联合体、枚举类型等。
(3) 指针类型:可以指向内存地址,用于构造各形态的动态或递归数据结构,如链表、树等。
(4) 空类型:void类型,也叫缺省型,用于描述值为空集,主要用于说明不返回值的函数或指向任意类型的指针等。
基本数据类型
数据类型 | 长度 | 取值范围 |
---|---|---|
char | 1 | -128~127 |
[signed] char | 1 | -128~127 |
unsigned char | 1 | 0~255 |
short [int] | 2 | -32768~32767 |
unsigned short [int] | 2 | 0~65535 |
int | 4 | -2147483648~2147483647 |
[signed] int | 4 | -2147483648~2147483647 |
unsigned [int] | 4 | 0~4294967295 |
long [int] | 4 | -2147483648~2147483647 |
[signed] long [int] | 4 | -2147483648~2147483647 |
unsigned long [int] | 4 | 0~4294967295 |
float | 4 | -2128 ~ +2128 |
double | 8 | -21024 ~ +21024 |
long double | 8 | -21024~ +21024 |
基本数据类型取值范围计算
1. 整型
short 长度为2字节,即 8bit ,第一位为符号位,剩下7位是数据位,所以short 取值范围为-27~ 27-1,即:-128~127(包含0,所以正数范围减1)
同理
int取值范围:-231~ 231-1
long取值范围:-231~ 231-1
2. 浮点型
浮点型数据的范围由指数位数决定
储存数据时,float 32bits 分配如下:
符号位 | 尾数位 | 指数位 |
---|---|---|
1bit | 8bits | 23bits |
0正1负 | 决定精度 | 决定范围 |
所以float 指数范围为-128~127。 其中负指数决定了浮点数所能表达的绝对值最小的非零数,正指数决定了浮点数所能表达的绝对值最大的数,即决定了浮点数的取值范围。float 的取值范围为-2128 ~ +2128。
double 64bits 分配如下:
符号位 | 尾数位 | 指数位 |
---|---|---|
1bit | 11bits | 52bits |
0正1负 | 决定精度 | 决定范围 |
所以double 指数范围为-1024~1023。 其取值范围为-21024 ~ +21024。
精度排行
short int<=int<=long int<=long long int
float<=double<=long double
数据类型转换
1. 自动类型转换
自动类型转换即编译器无需程序猿干预,自动进行数据类型转换。
(1) 将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换。
在赋值运算中,赋值号两边的数据类型不同时,需要把右边表达式的类型转换为左边变量的类型,这可能会导致数据失真,或者精度降低;所以说,自动类型转换并不一定是安全的。对于不安全的类型转换,编译器一般会给出警告。
(2) 在不同类型的混合运算中,编译器也会自动地转换数据类型,将参与运算的所有数据先转换为同一种类型,然后再进行计算。转换按数据长度增加的方向进行,以保证数值不失真,或者精度不降低。具体规则如下图:
自动类型转换示例:
#include<stdio.h>
int main(){
float PI = 3.14159;
int s1, r = 5;
double s2;
s1 = r * r * PI;
s2 = r * r * PI;
printf("s1=%d, s2=%f\n", s1, s2);
return 0;
}
运行结果:
s1=78, s2=78.539749
在计算表达式 r* r* Pi 时,r 和 Pi 都被转换成 double 类型,表达式的结果也是 double 类型。但由于 s1 为整型,所以赋值运算的结果仍为整型,舍去了小数部分,导致数据失真。
2. 强制类型转换
自动类型转换是编译器根据代码的上下文环境自行判断的结果,有时候并不能满足所有的需求。因此程序员也可以自己在代码中明确地提出要进行类型转换,这称为强制类型转换。强制类型转换必须有程序员干预。其格式为
(type_name) expression
type_name为新类型名称,expression为表达式。例如:
(float) a; //将变量 a 转换为 float 类型
(int)(x+y); //把表达式 x+y 的结果转换为 int 整型
(float) 100; //将数值 100(默认为int类型)转换为 float 类
下面是一个需要强制类型转换的经典例子:
#include <stdio.h>
int main(){
int sum = 103; //总数
int count = 7; //数目
double average; //平均数
average = (double) sum / count;
printf("Average is %lf!\n", average);
return 0;
}
运行结果:
Average is 14.714286!
sum 和 count 都是 int 类型,如果不进行干预,那么sum / count的运算结果也是 int 类型,小数部分将被丢弃;虽然是 average 是 double 类型,可以接收小数部分,但是心有余力不足,小数部分提前就被“阉割”了,它只能接收到整数部分,这就导致除法运算的结果严重失真。
既然 average 是 double 类型,为何不充分利用,尽量提高运算结果的精度呢?为了达到这个目标,我们只要将 sum 或者 count 其中之一转换为 double 类型即可。上面的代码中,我们将 sum 强制转换为 double 类型,这样sum / count的结果也将变成 double 类型,就可以保留小数部分了,average 接收到的值也会更加精确。
3. 类型转换具有临时性
无论是自动类型转换还是强制类型转换,都只是为了本次运算而进行的临时性转换,转换的结果也会保存到临时的内存空间,不会改变数据本来的类型或者值。
数值溢出
以短整型变量为例,有符号变量short 与无符号变量unsigned short 长度都为16位。short变量的取值范范围是-32768~+32767(-215 ~ 215-1),而unsigned的取值范围是0~ 65535(0~216-1)下图展示了它们的溢出情况:
符号短整型最大值为+32767,再+1之后就会溢出为-32768;无符号短整型最大值为 +65535,+1后溢出为0.
例如:
#include <iostream>
using namespace std;
int main()
{
short a = SHRT_MAX; //此处 SHRT_MAX表示有符号short数据类型的最大值
unsigned short b = a;
cout << "a = " << a << " b = " << b << endl;
a++;
b++;
cout << "a = " << a << " b = " << b << endl;
return 0;
}
运行结果:
a = 32767 b = 32767
a = -32768 b = 32768
移位操作
移位操作包括左移和右移,右移又分为逻辑右移和算术右移。
左移:x<<n
x左移n位,并在右端补零,左移一位相当于乘2运算 。
右移:
逻辑右移:x>>n
x右移n位,并在左端补零。
算术右移:x>>n
x右移n位,并在左端补最高有效位的值。
右移时无符号数直接移位和补零,即采用逻辑右移;有符号数大多采用移位和补最高有效位,即算术右移。
以下题为例:
(1) unsigned char x=3
x<<1是多少?x>>1是多少?
(2) char x=3
x<<1是多少?x>>1是多少?
(3)char x=-3
x<<1是多少?x>>1是多少?
3的二进制数是00000011;-3的二进制数是(补码)11111101。无符号unsigned char采用逻辑右移;有符号char大多采用算术右移。结果如下:
unsigned char | unsigned char | char | char |
---|---|---|---|
x | 00000011 (3) | 00000011 (3) | 11111101 (-3) |
x<<1 | 00000110 (6) | 00000110 (6) | 11111010 (-6) |
x>>1 (逻辑右移) | 00000001(1) | ||
x>>1 (算术右移) | 00000001(1) | 11111110 (-2) |
参考
https://blog.csdn.net/qq_15020543/article/details/81152006
http://c.biancheng.net/view/1775.html
https://blog.csdn.net/u013271921/article/details/40540011
https://blog.csdn.net/happy_gp_/article/details/4806003?utm_source=distribute.pc_relevant.none-task