double型与float型之间的相互转换问题

再战江湖之2023 2008-07-30 08:32:53
我做的单片机项目,目前遇到这样一个问题:
通过串口接收到一个double型的数据,是其内存存放状态,总共8个字节,类似于4A D8 12 4D FB 21 09 40(也就是3.1415926),而在处理时因为KEIL只能处理4个字节的数据,所以根据IEEE标准将double型转换为float型,而处理完毕后还要将float型转换成double型通过串口发送出去。这中间就存在一个转换问题,即如何在double型和float型之间进行转换,目前double转float已实现,float转double尚未成功。
float转double型时不知道底数部分应该如何对应或者说取舍。
float型底数23位,double型底数52位,double型底数比float底数多的这部分应该如何处理,加0吗?
请注意我用的是C语言,KEIL环境,应该只能根据IEEE标准转换,没有转换函数,请大家各抒己见,最好有算法或代码。
...全文
10164 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
秋悦恒迹 2011-12-16
  • 打赏
  • 举报
回复
老兄,PLC不支持double,你是怎么将double转化为float型的
  • 打赏
  • 举报
回复
mllee79兄看来也是对这个很熟悉的,发的还有代码,并且一直积极参与讨论,多谢
好了,问题解决,结帖
薛定谔之死猫 2008-07-31
  • 打赏
  • 举报
回复
单片机的C环境和普通桌面和服务器的C环境有着很大的区别,觉得还是看相关的手册比较把稳
薛定谔之死猫 2008-07-31
  • 打赏
  • 举报
回复
float被自动扩展为double
尽管在ANSI C中情况不再如此,但最初浮点数常量的精度都是double型的,所有表达式中float变量总被自动转换成double。这样做的理由从未公诸于众,但它与PDP-11中浮点数的硬件表示方式有关。首先,在PDP-11和VAX中,从float转换成double的代价非常小,只要在后面增加一个每位均为0的字即可。如果要转换回来,去掉第二个字就可以了。其次,要知道在某些PDP-11的浮点数硬件表示形式中有一个位运算模式位(mod bit),你可以只进行float的运算,也可以只进行double的运算,但如果想在这两种方式间切换,就必须修改这个位来改变运算模式。
——摘自《C专家编程》

敬请参考,呵呵
aaajj 2008-07-31
  • 打赏
  • 举报
回复
学习
mLee79 2008-07-31
  • 打赏
  • 举报
回复
double 只是占个位置而已, 随便换成个 8 字节的类型即可, 比如这样( 小端序 ) :

#include <stdio.h>

typedef unsigned long u32;

typedef struct x_double_type_t x_double_type;
struct x_double_type_t
{
u32 low_32;
u32 hi_32 ;
};

#define double x_double_type

void f2d( float f , double *x )
{
u32 a , b;
u32 uf = *(u32*)&f;
u32*ux = (u32*)x;

ux[0] = ux[1] = 0;
ux[1] |= uf&0x80000000;

a = (uf&0x7f800000)>>23;
b = uf&0x7fffff;
a += 1024 - 128;
ux[1] |= a<<20;
ux[1] |= b>>3 ;
ux[0] |= b<<29;
}

int main()
{
float f = 3.14159265f;
double x;

f2d( f , &x );
printf( "%lf\n" , x );

while( 1 == scanf( "%f" , &f ) )
{
f2d( f , &x );
printf( "%lg\n" , x );
}

return 0;
}

mLee79 2008-07-31
  • 打赏
  • 举报
回复
偶晕死,你觉得你这样好记么,很显然的是记住 INF 的阶码是最简单的, float 的 INF 的阶码为 128 , double 的为 1024 ...
你看东西不仔细, 指数全0 (非规范化数及0) , 全1( INF && NaN ) 都表示特别的意义 ...
规范化的单精度浮点数 阶码范围是 -126 -- 127 , 不是 128 , 双精度数是 -1022 - 1023 ....
非规格化数单精度数表示的最小的数可以是 2^-149 , double 可以到 2^-1074 ....
  • 打赏
  • 举报
回复
结果一样的,但是意思不一样
但因為指數應可正可負,
所以 IEEE 規定, 此處算出的次方須減去 127 才是真的指數,
所以 float 的指數可從-126 到 128.
double 型態有 11 bits, 算出的值須減去 1023
所以double 的指數可從 -1022 到 1024.
mLee79 2008-07-31
  • 打赏
  • 举报
回复
偶晕, 1024-128难道和1023-127不一样嗦...
  • 打赏
  • 举报
回复
mlee79兄给出了代码,但是里边也存在问题:
最重要的是keil里边不支持double类型,所有的double类型都是按照float类型进行存放的,所以不能定义double类型,那是没有意义的。
不要考虑定义double类型,因为如果可以的话,我就不存在这个问题,直接定义公用体就可以了。
zzzlll1983 2008-07-31
  • 打赏
  • 举报
回复
学习
  • 打赏
  • 举报
回复
问题已经解决。
我是按照IEEE754标准实现转换,中间需要计算double型指数位,底数不足部分填充0。
MLEE79兄代码里边似乎有些问题:a += 1024 - 128;似乎是要计算double的指数,但是似乎应该是a += 1023 - 127;
参见IEEE754,另外KEIL不支持8个字节数据类型运算,包括double,double是被当作float类型进行处理了,所以只要是定义double类型的都是没有意义的。定义double型的跟定义float型的是一样的效果。但thank you all the same!
另外发现KEIL是大端模式,VC6.0是小端模式。
搞定了,爽!
mLee79 2008-07-30
  • 打赏
  • 举报
回复 1
随手写的, 未考虑未规格化数, NaN , INF ..

#include <stdio.h>

void f2d( float f , double *x )
{
unsigned long a , b;
unsigned long uf = *(unsigned long*)&f;
unsigned long*ux = (unsigned long*)x;

ux[0] = ux[1] = 0;
ux[1] |= uf&0x80000000;

a = (uf&0x7f800000)>>23;
b = uf&0x7fffff;
a += 1024 - 128;
ux[1] |= a<<20;
ux[1] |= b>>3 ;
ux[0] |= b<<29;
}

int main()
{
float f = 3.14159265f;
double x;

f2d( f , &x );
printf( "%lf\n" , x );

while( 1 == scanf( "%f" , &f ) )
{
f2d( f , &x );
printf( "%lg\n" , x );
}

return 0;
}
  • 打赏
  • 举报
回复
现在有个问题是这样的:
float型指数为8个bit,double型指数为11个bit,如果我已经计算出来double型的指数是多少之后如何对应存放到double型的对应bit里边?
K行天下 2008-07-30
  • 打赏
  • 举报
回复
那你就要看标准里面的double和float具体怎么实现的,然后自己对照着转换
K行天下 2008-07-30
  • 打赏
  • 举报
回复
那你就要看标准里面的double和float具体怎么实现的,然后自己对照着转换
  • 打赏
  • 举报
回复
这样不行的,因为我说过了:“在处理时因为KEIL只能处理4个字节的数据”,单片机里边不能处理8个字节的double类型,另外通过串口过来的是16进制字节,像这样4A D8 12 4D FB 21 09 40,而非2309.12E-15这样的。
只能通过IEEE标准自己转换,我想知道float转double型的算法,越详细越好
iu_81 2008-07-30
  • 打赏
  • 举报
回复
char *s;
double x;
s = " -2309.12E-15";
x = atof( s );

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧