Hello!大家好啊!我是你们的jw3啊,本期我将会带领大家去了解数据是如何在计算机里面存储调用的,也会讲一些基础的题目来方便大家更好的学习,希望本期文章对大家有所帮助
文章目录
提出问题
1.你想知道C语言的整型与浮点型在计算机中如何存储的吗?
2.你想知道我们的输入数字的算法是怎么进行的吗?
别急,本章会为大家一一解惑
前言
在学习本章内容之前我们要会一些基础知识:
1.计算机是通过二进制形式来储存的,整数在内存中存储和运算都要先转换成补码;
2.之前我们提到的整型与浮点型所占字节大小,比如char占一个字节,int占4个字节,float占4个字节…
3.一个字节等于八个比特位;
4.计算机内存储的数据都是补码(计算也是通过补码来进行计算);
5.打印在屏幕的数据是原码,计算机会自动进行转换显示出来;
6.正数与负数原、反、补码的形式是怎么样的。
上面的知识大家有地方不懂也没有关系,正文内容我会将这些知识深入拓展,方便大家理解,话不多说,进入正文。
一、C语言的数据类型有哪些?
C语言有4种数据类型,如下图:
这里我们着重来讲一下基本数据类型:
二、整型类型的存储
整型的所有类型都包括有符号数(signed)和无符号数(unsigned)
注:char也算是整型数据,别看它是一个字符类型的,但是它在ASCLL表里面对应的是整数,所以说char算是整型数据
这里我们介绍char类型的,因为整型数据的存储都是相通的,而且char类型比较简单,方便我们学习
char存储的范围大小
我们知道char占一个字节的大小,也就是8个比特位,只有0与1这两个值。所以char类型的全部值就是下图所示:
接下来我们分析分析
1、有符号char(signed char)
从0000 0000到0111 1111想必大家都知道。在有符号数中,最高位表示符号,0表示正,1表示负,正数的原、反、补码相同,所以0000 0000到0111 1111就是数字0到127(进制之间的转换之前有讲过 进制间的转换 )(下面我们会讲小数部分的进制转换问题)。
接下来我们继续,既然正数分析完了我们再来分析负数,我们这次倒着看从1111 1111到1000 0000
从上图可以看出1111 1111所表示的数字是-1,大家可千万要注意不要把这个符号位1弄错了。既然1111 1111表达的是-1,那么1111 1110呢?
可以看出1111 1110转换成补码为1000 0010也就是-2,刚刚的1111 1111是-1,现在的1111 1110是-2,那么我们就能判断出1111 1111到1000 0001就是-1到-127
而此时还剩下一个数—1000 0000,这个数该怎么理解呢?
有人就会问了,1000 0000难道是-0?它怎么取反,怎么减一呢?
其实这个数我们可以直接把它当成-128,我们可以把它看成1000 0000=1000 0001-1,转换成补码就是-127-1=-128,这个数可以直接这样来看
所以我们把char的范围就整理了一遍
可以看出,有符号char(signed char)范围大小是从-128—127
为了方便大家进一步理解,我用一张图来表示
大家通过这张图应该更容易理解signed char 的范围与一些注意点
2、无符号char(unsigned char)
这个就容易理解了,无符号char表示第一位不管是0是1都是有效数字,直接计算即可
所以0000 0000到0111 1111是0到127,而1000 0000就是1*2^7=128,
直到1111 1111就是2的0次方到2的7次方之和也就是255
可以很容易看出无符号char范围是0到255
还是用一张图表示
看到这里相信大家对char类型的存储有了一定的认识
接下来再讲点其他内容
3、补充知识点
A、数据在计算机内部的运算
先来看一段代码
#include<stdio.h>
int main()
{
int a = 1;
int b = -1;
printf("%d\n", a + b);
return 0;
}
很容易看出来答案是0
但是在计算机内部的运算大家知道吗?
可以能大家会认为是两个数原码相加,我们来试试看
由上图可以看出,a和b在计算机里面是用补码进行相加的
补充:运算的时候是在cpu里面运算的,而cpu只有加法运算,当出现减、乘、除法运算都会转换成加法来运算
B、大小端存储
可以看到a的值是ff bb 00 00,但是在内存里面存放的是00 00 bb ff,
好像反了啊,是不是电脑出故障了?
其实这就涉及到大小端储存了:
当数据的低位存放在内存低地址处,数据高位存放在内存高地址处时,称为小端储存,也叫小端字节序
当数据的低位存放在内存高地址处,数据高位存放在内存低地址处时,称为大端储存,也叫大端字节序
接下来用一段代码来判断大小端:
#include<stdio.h>
int main()
{
int a = 1;
char* p = (char*) & a;//我们只用判断前面一个字节是数字0还是1就可以判断出大小端了
if (*p == 1)//如果第一个字节放的是1,那么就是10
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
这样写又有点太low了,我们改进一下
#include<stdio.h>
int cherk()
{
int a = 1;
char* p = (char*)&a;
/*if (*p == 1)
return 1;
else
return 0;*/
//return *p;
}
int main()
{
int ret = cherk();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
上面两种注释方法都可以,只不过下面只用一个return更方便
小结
我们学习到signed char的范围是-128~127,unsigned char的范围是0~255;计算机有大端与小端两种存储方法。
代码如下(示例):
data = pd.read_csv(
'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())
该处使用的url网络请求的数据。
三、整型提升
上面我们对char类型储存有了一定的了解,其他的整型,int short,long等与char类型原理一样,只不过范围更广
整型提升:用一句话概括就是:短整型以及字符类型的变量之间或者相互进行算术运算操作时,就会发生整型提升。一般来说整型提升前面会补符号位。
我们通过几道例题来研究研究整型提升:
例题1
char a=-1;
signed char b=-1;
unsigned char c=-1;
printf("%d\n%d\n%d\n",a,b,c);
我们来分析分析:
signed char是有符号char,而char默认就是有符号的形式,所以signed char和char过程差不多一模一样
所以可以看到打印值是-1,-1和255
例题2
char a=-128;
char b=128;
printf("%u\n%u\n",a,b);
继续分析:
可以看出如果对char类型范围运用不清楚的话很容易踩坑
例题3
unsigned char a=0;
for(a=0;a<=255;a++);
printf("hehe\n")
这一题打印出来的是什么呢?
我就不卖关子了,会死循环打印hehe
通过这3道例题相信大家对整型提升有一定的了解,整型提升就是要绕一个弯子,大家以后多注意就行
四、浮点型类型储存
1.存入
我们主要讲float类型,double类型与float类型原理相同,在有区别的地方我会提出来的
我们看到打印结果第一行和最后一行是我们想要的答案,但是中间两行不是我们想要的,这是为什么呢?
那是因为我们规定,浮点型类型储存计算公式位:(-1) ^S * M * 2^ E
(-1)^S表示符号位,s=0表示正数,s=1表示负数
M是有效数字,范围是1<=M<2
E表示次数,同时也是一个无符号数
举个例子:float a = 5.5:
这就是一个十进制浮点数储存如何储存在计算机里面的过程
2、取出
浮点数存入我们了解了,那如何取出呢?
取出分三种
1.取出的E不为全0或者全1
上图例子:40b00000
取出:S取0
(float)E取出时减127,129-127=2,所以E=2。(double取出时,E要减1023)
M取出时要在整数部分补上1,后面接小数部分
(-1)^ 01.0112 ^ 2---->1*101.1—>5.5
2、取出的E为全0
E由之前加127得到,所以原来的E+127=0,我们直接返回写成:
(-1)^s*0.0112 ^1-127—>(-1) ^ S0.011*2 ^ -126
在E为全0的时候取出数据时,M前面不用补上1,表示一个正负无限接近于0的数
3、取出的E为全1
直接写成(-1)^S1.0112 ^ 128,表示一个正负无穷大的数字
3、例题
我们再来看看:
可以看出答案是一模一样的,由此推断我们的做法是正确的
最后
希望个位看官老爷有所收获,也多多支持小编,不胜感激,我们下期见!