数据在内存中的存储

1、数据类型

整形家族:char  short  int  long(有无符号)

浮点型家族:float      double

构造类型:数组类型、结构体类型struct、枚举类型enum、联合类型union

指针类型:int *pi,char *pc,float *pf,void *pv

空类型:void表示空类型(无类型),通常用于函数返回类型、函数的参数、指针类型

2、整形在内存中的存储

2.1 原码、反码、补码

最高位为符号位,0表示“正”,1表示“负”。正数原反补相同

负数求补码,二进制表示原码,符号位不变,其他位取反为反码,+1为补码

2.2 大小端介绍

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;

小端则低存低,高存高。(低位字节序,高位字节序)

为什么有大端和小端:这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit,但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题,因此就导致了大端存储模式和小端存储模式

内存中存的都是补码:

       Signed char:正数:0000 0000->0(对应十进制的0)

                                   0000 0001->1

                                   0000 0010->2

                                   0000 0011->3

                                   ……

                                   0111 1111->127

                            负数:1000 0000->-128(直接转换)

                                   1000 0001->-127

                                   1000 0010->-126

                                   ……

                                   1111 1110->-2

                                   1111 1111->-1(八个全1是-1在内存中存的补码,取反+1

                                                                                转换为原码是1000 0001)

       unsigned char:0000 0000->0

                             0000 0001->1

                             0000 0010->2

                             0000 0011->3

                             ……

                             0111 1111->127

                             1000 0000->128

                             1000 0001->129

                             ……

                             1111 1110->254

                             1111 1111->255

       signed short:0000 0000 0000 0000->0

                            0000 0000 0000 0001->1

                            ……

                            0111 1111 1111 1111->32767

                            1000 0000 0000 0000->-32768

                            1000 0000 0000 0001->-32767

                            ……

                            1111 1111 1111 1110->-2

                            1111 1111 1111 1111->-1

       unsigned short:0000 0000 0000 0000->0

                            0000 0000 0000 0001->1

                            0111 1111 1111 1111->32767

                            1000 0000 0000 0000->32768

                            1000 0000 0000 0001->32769

                            ……

                            1111 1111 1111 1110->65534

                            1111 1111 1111 1111->65535

总结:signed char取值为-128~127

       unsigned char取值为0~255

       signed short取值为-32768~32767

       unsigned short取值为0~65535

例1:char a = -1

signed char b = -1

unsigned char c = -1

printf("a=%d,b=%d,c=%d",a,b,c)

输出结果是什么?

答:a=-1,b=-1,c=255

解释:有符号char取值-128~127,所以a,b赋值为-1

              -1的原反补码:

原码:1000···0000 0000 0000 0000 0000 0000 0001(共32位)

反码:1111···1111 1111 1111 1111 1111 1111 1110

补码:1111···1111 1111 1111 1111 1111 1111 1111

因为a被赋值为-1,-1是32位的,而内存中存的是补码,把原转补后仍为32位,char a仍放不下,故截断,最后存到a中的是8个1,而%d 打印的是有符号的整型,故整型提升,提升补码,因高位为1,全补1,再取反+1到原码,最后打印原码。

对于无符号的c,因c本身为无符号的数,所以高位补0,而最后打印有符号整型,而正数的原反补码相同,则c打印出来为255

总结:整型提升看它自身原本类型

              有符号:负数高位补1

                            正数高位补0

              无符号:高位补0

例2:char a = -128

printf("%u",a)

printf("%d",a)

打印结果是什么?

答:结果为4294967168    -128

解释:-128原码:1000 0000 0000 0000 0000 0000 1000 0000

反码:1111 1111 1111 1111 1111 1111 0111 1111

补码:1111 1111 1111 1111 1111 1111 1000 0000

截断后仅保留后八位1000 0000

若以%u打印就是无符号整型,而正数的原反补码相同,则打印为一个很大的正数,若以%d打印需转原码

(原码转补码要取反+1,补码转原码也可以取反+1)

打印之前先进行整型提升,且a是有符号类型,赋给a的值是个负数,所以高位补1

补码:1111 1111 1111 1111 1111 1111 1000 0000->4294967168

反码:1000 0000 0000 0000 0000 0000 0111 1111

原码:1000 0000 0000 0000 0000 0000 1000 0000->-128

3、浮点数存储规则

根据国际标准IEEE(电气和电子工程师协会)754,任意一个二进制浮点数V可以表示成以下形式:(-1)^S * M * 2^E

(-1)^S表示符号位,即-1的S次幂,当S=0,V为正数;当S=1,V为负数

M表示有效数字,大于等于1,小于2

2^E表示指数位,2的E次幂

例:V=5.0(十进制)→ 101.0(二进制)→ 1.01 * 2^2(底数是2的原因为:在十进制中每一位是10的几次幂,在二进制中每一位就是2的几次幂)

= (-1)^0 * 1.01 * 2^2

S=0  M=1.01  E=2

但对于V=9.6→ 1001.100……(十进制转二进制,点前点后分别写成二进制)

点前第一位的权重是2的0次方,点后第一位是2的-1次方(就是0.5),但无论后边凑多少位,总是无法凑到0.6,此时就会出现精度丢失

对于float浮点数IEEE 754规定:

对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下23位为有效数字M

对于64位的浮点数,最高的1位是符号位S,接11位E,剩52位M

3.1 IEEE 754对有效数字M和指数E,还有一些特别规定:

前面说过,1<=M<2,也就是说,M可以写成1.XXXXXX的形式,其中XXXXXX表示小数部分

IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的XXXXXX部分,比如保存1.01时候,只保存01,等到读取的时候,再把第一位的1加上去,这样做的目的,是节省1位有效数字,以32位浮点数为例,留给M只有23位

将第一位的1舍去以后,等于可以保存24位有效数字

3.2 至于指数E,情况就比较复杂:

首先,E为一个无符号整数(unsigned int)

这意味着,如果E为8位,它的取值范围为0~255,如果E为11位,它的取值为0~2047,但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023,比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10 + 127 = 137,即10001001。

3.3 然后,指数E从内存中取出还可以再分成三种情况:

(1) E不全为0或不全为1:

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1

比如:

0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0 * 2^-1,其阶码为-1 + 127 = 126,表示为01111110(8位),而尾数1.0去掉整数部分为0,补齐0到23位,则其二进制表示为:

0 0111 1110 000 0000 0000 0000 0000 0000

(2) E全为0:

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.XXXXXX的小数。这样做是为了表示±0,以及接近于0的很小的数字

(3) E全为1:

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位S)

例:int n = 9;

float* pFloat = (float*)&n;

printf("%d", n);

printf("%f", *pFloat);

*pFloat = 9.0;

printf("%d", n);

printf("%f", *pFloat);

打印结果是什么?

答:9

0.000000

1091567616

9.000000

解释:9是正数,原反补相同,补码为0000 0000 0000 0000 0000 0000 0000 1001

但站在pFloat的角度认为内存中存的是浮点数编码,分成三部分:

0 00000000 000000000000000001001

E为全0的情况,E=1-127=-126

M=0.00000000000000000001001

故最后打印的是+0.000000000000000001*2^(-126)

再看后两个,刚才是以整数形式存进去,再以整型、浮点型打印的。现在以浮点数形式存进去,再以整型、浮点型打印的。

而以浮点数存,先写成二进制,再找S、E、M,拼成32位

9.0 → 1001.0 → 1.001 * 2^3

S=0,E=3,M=1.001(3 + 127 = 130,130二进制10000010)

所以二进制表示为0 10000010 00100000000000000000000

此时以整型打印是一个很大的正数,1091567616

最后以浮点数打印是9.000000

总结:相同类型的数据存储和打印是相同的

基于粒子群优化算法的p-Hub选址优化(Matlab代码实现)内容概要:本文介绍了基于粒子群优化算法(PSO)的p-Hub选址优化问题的研究与实现,重点利用Matlab进行算法编程和仿真。p-Hub选址是物流与交通网络中的关键问题,旨在通过确定最优的枢纽节点位置和非枢纽节点的分配方式,最小化网络总成本。文章详细阐述了粒子群算法的基本原理及其在解决组合优化问题中的适应性改进,结合p-Hub中转网络的特点构建数学模型,并通过Matlab代码实现算法流程,包括初始化、适应度计算、粒子更新与收敛判断等环节。同时可能涉及对算法参数设置、收敛性能及不同规模案例的仿真结果分析,以验证方法的有效性和鲁棒性。; 适合人群:具备一定Matlab编程基础和优化算法理论知识的高校研究生、科研人员及从事物流网络规划、交通系统设计等相关领域的工程技术人员。; 使用场景及目标:①解决物流、航空、通信等网络中的枢纽选址与路径优化问题;②学习并掌握粒子群算法在复杂组合优化问题中的建模与实现方法;③为相关科研项目或实际工程应用提供算法支持与代码参考。; 阅读建议:建议读者结合Matlab代码逐段理解算法实现逻辑,重点关注目标函数建模、粒子编码方式及约束处理策略,并尝试调整参数或拓展模型以加深对算法性能的理解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值