float、real、int、integet类型问题;float类型转换问题

前言

最近在一个项目协议中遇到了一个问题,就是数据类型问题,
主要有一些之前没见过的类型在计算机占位大小,及在串口获取后从数组buf转换float类型问题,在这里就将C语言常见的数据类型都记录下;
要想弄清楚buf转换位float数正确,就得先了解清除float在计算机中的存储格式逻辑。
本篇文章主要介绍常见c语言在计算机占位大小,数组转换float类型问题;

1、C语言一些类型介绍

1.1、基本类型所占字节大小

类型16编译器32编译器64编译器
char111
long448
shor222
float444
double888
int244
short int222
long long888
real4444
real8888
指针 *248

1.2、real、integet类型

1.2.1、 real 和 float 数据类型 的区别

real 有real4、real8、real10等类型

类型主体存储数据不同表示范围不同
float浮点型数据类型数据类型用于存储单精度浮点数或双精度浮点数-3.4E+38 ~ 3.4E+38
real4数据类型用于存储单精度浮点数数据类型保存单精度浮点数。它是一种近似数字数据类型,在算术运算后容易产生舍入误差。-3.402823e+38 到 3.402823e+38,最趋近于零的数为 1.175494351e-38

储存方式

类型符号位指数位数指数偏移
float(32位)1位符号位(s)8位指数(e)23位尾数(m,共32位)127(7FH)
double1位符号位(s)11位指数(e)52位尾数(m,共64位)1023(3FFH)
real*41位符号位(s)8位指数(e)23位尾数(m,共32位)127(7FH)
real*81位符号位(s)11位指数(e)52位尾数(m,共64位)1023(3FFH)
real*101位符号位(s)15位指数(e)64位尾数(m,共80位)16383(3FFFH)

1.2.2、integer和int的区别

Integer是java为int提供的封装类。Integer 是一个类,是int的扩展,定义了很多的转换方法。本人属于C语言阵营,对JAVA不了解就不多描述,我在做项目时直接看作int类型>o< 。
1、Integer是Int的包装类,Int是八种基本数据类型之一。
2、Integer变量必须实例化以后才可以使用,而Int变量不需要实例化。
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象,而Int是直接存储数据值。
4、Integer的默认值是null,Int的默认值是0。

2、float 类型在计算机中储存逻辑

其中float的存储方式如下图所示:
在这里插入图片描述
而双精度的存储方式为:
在这里插入图片描述

2.1、float存储举例

将123.625数据在计算机内存中存储是怎样的格式呢
1、首先将123.625转换为假定的二进制
123 二进制 111 1011
0.625 二进制 101
那么123.625二进制为 111 1011.101
2、将111 1011.101的小数点左移,直到小数点前面只剩一位1
移动了6位,那么可以理解为 1.1 1101 1101*2^6

底数:因为小数点前必为1,所以IEEE规定只记录小数点后的就好。所以,此处的底数为:1 1101 1101
指数:实际为6,必须加上127,所以为133。也就是1000 0101
符号:整数,所以是0

最终 123.625在内存中储存的格式是
0 1000 0101 111 0111 0100 0000 0000 0000

2.1.1、在线float、double数转换链接

https://tooltt.com/floatconverter/

2.2、将计算机中的float类型数读取出来十进制表示

例如:将存储的一个float数输出出来,有了上面的存逻辑,读取的话就方便多了
这里用键盘输入计算机存储的二进制来模拟实现
例:01000010110010001000000000000000 (该数为:100.25)

S符号位(0表示正数,1表示负数)E指数m尾数e指数偏移
01000010110010001000000000000000127

符号位: S=0
指数偏移: e=127
指数: E=(10000101)2 = 133
E-e=133-127=6
尾数: m=(10010001000000000000000)2将后面的0去掉 再在前面补上必为1的整数值1.10010001
V= (1.10010001)2*2^6= (1100100.01)2
整数 :(1100100)2=100 小数:(0.01)2=0.25

//计算公式
//当E(各位)为全'0'时
//在real*4时:
V = (-1)^S*2^(-126)*m;
//在real8时:
V = (-1)^S*2^(-1022)*m;
//当E(各位)不为全'0'且不为全'1'时
V = (-1)^S*2^(E-e)*(m+1);

V=(-1)^0 2^(133-127)(0.10010001+1);

注意:
1、这里的(0.10010001)2指的是二进制方式,不是十进制0.10010001的值
2、*2^6并不是去乘以64,因为这里是二进制所以这里可以理解为小数点向后移6位

3、将四字节转换为float数

原理逻辑:
将这四个字节转换成一个32位无符号的数值,将该数值的地址指针强制转换为float指针类型(float*),在取出它的值*(float*)

//四个字节转换为一个float数
float Byte_to_Float(uint8_t *p)
{
	float float_data=0.0;
	unsigned long longdata = 0;
	longdata = (*p<< 24) + (*(p+1) << 16) + (*(p + 2) << 8) + (*(p + 3) << 0);
	float_data = *(float*)&longdata;
	return float_data;
}

4、将float数用四字节表示

原理逻辑:
当计算机读取一个float数时,计算机会找到这个数的地址然后以存储的指针类型(float格式)一次性读取四个字节,并以float格式转换为十进制的值
而当计算机要读取一个字符时,这时他是一次性读取一个字节;
所以要将float转为char时是需要连续读取四次即可。

//浮点数转换为四字节
void FloatToByte(float floatNum,uint8_t* byteArry)
{
    char* pchar=(char*)&floatNum;
    for(int i=0;i<4;i++)
    {
        *byteArry=*pchar;
        pchar++;
        byteArry++;
    }
}

时间:20230705

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是我写的一个ArrayLists类,实现了你所述的各种方法: ```java public class ArrayLists { private Object[] arr; private int size; public ArrayLists() { arr = new Object[8]; size = 0; } public void add(Object o) { if (size == arr.length) { int newLength = size * 2 + 1; Object[] newArr = new Object[newLength]; System.arraycopy(arr, 0, newArr, 0, size); arr = newArr; } arr[size] = o; size++; } public Object get(int i) { if (i < 0 || i >= size) { System.out.println("数组下标越界"); return null; } return arr[i]; } public int length() { return size; } public Object del(int i) { if (i < 0 || i >= size) { System.out.println("数组下标越界"); return null; } Object result = arr[i]; for (int j = i; j < size - 1; j++) { arr[j] = arr[j + 1]; } size--; return result; } public void update(int i, Object o) { if (i < 0 || i > size) { System.out.println("数组下标越界"); return; } if (i == size) { add(o); return; } for (int j = size - 1; j >= i; j--) { arr[j + 1] = arr[j]; } arr[i] = o; size++; } } ``` 这个类使用了一个Object类型的数组arr来保存元素,以及一个整数变量size来表示当前存储到该对象中的元素个数。在构造函数中,我们初始化了数组arr,使其可以保存8个元素。 add方法用于在最后插入一个Object对象,并在需要时自动扩容。如果当前存储的元素个数等于数组的长度,我们就将数组扩容为当前存储的个数 * 2 + 1。 get方法用于根据下标返回数组中对应的对象。如果下标为负数或超出当前存储的个数,我们输出"数组下标越界"。 length方法用于返回当前存储到该对象中的元素个数,注意不是数组的长度。 del方法用于根据下标删除数组中的内容,并将数组后面的内容依次向前移动。如果下标为负数或大于等于当前存储的元素个数,我们输出"数组下标越界"。 update方法用于在指定下标位置上插入对象,原位置及后续内容统一向后移动一位。如果下标为负数或大于当前存储的元素个数,我们输出"数组下标越界"。 最后,我们创建了一个ArrayLists对象,存入了9个其他类型的对象,并依次调用各个方法进行测试。你可以根据需要修改对象中存储的元素个数,以及需要插入、删除、修改的元素位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值