sscanf 十六进制转双精度浮点数问题

frankzhong_bjtu 2013-07-10 12:49:35
各位大神,小弟有个很基础的问题。现在在写一个程序要把十六进制的字符数组转换成双精度浮点数,想用sscanf,因为之前单精度和整形的转换都没问题,但双精度的就出错了,我的程序:

char YA_HEX[20];
double YA_Num;
memset((char *)YA_HEX,0,1*20);
...
//中间计算赋值
...
sscanf(YA_HEX,"%x",&YA_Num);
cout<<"HEX:"<<YA_HEX<<endl;
cout<<"Num:"<<YA_Num<<endl;

比如YA_HEX赋值bf0884bd88c6ec6e,应该转换成的结果是96180.1541071667,但我输出的YA_Num是-9.25596e+061(其对应的十六进制是f3 1f 26 29 cc cc cc cc)而且当YA_HEX数据变的时候输出的还是这个结果。。对数制转换有点困惑,是double不可以用sscanf么,请各位大神指教!谢谢啦!
...全文
789 24 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
frankzhong_bjtu 2013-07-11
  • 打赏
  • 举报
回复
引用 20 楼 zhao4zhong1 的回复:
[quote=引用 15 楼 frankzhong_bjtu 的回复:]
[quote=引用 8 楼 zhao4zhong1 的回复:]
Collapse AllExpand All Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript
Visual Basic
C#
Visual C++
J#
JScript
Run-Time Library Reference
printf Type Field Characters
See Also Send Feedback


The type character is the only required format field; it appears after any optional format fields. The type character determines whether the associated argument is interpreted as a character, string, or number. The types C, n, p, and S, and the behavior of c and s with printf functions, are Microsoft extensions and are not ANSI compatible.

Character
Type
Output format

a
double
Signed hexadecimal double precision floating point value having the form [−]0xh.hhhh p±dd, where h.hhhh are the hex digits (using lower case letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point.

A
double
Signed hexadecimal double precision floating point value having the form [−]0Xh.hhhh P±dd, where h.hhhh are the hex digits (using capital letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point.
[/color]


Note If the argument corresponding to %s or %S is a null pointer, "(null)" will be printed.

Note In all exponential formats, the default number of digits of exponent to display is three. Using the _set_output_format function, the number of digits displayed may be set to two, expanding to three if demanded by the size of exponent.

Security Note The %n format is inherently insecure and is disabled by default; if %n is encountered in a format string, the invalid parameter handler is invoked as described in Parameter Validation. To enable %n support, see _set_printf_count_output.

See Also
Concepts
printf, _printf_l, wprintf, _wprintf_l
Send feedback on this topic to Microsoft.


是要用“%a”么,但我试了一下,没有作用。。sscanf没有给double赋值,是因为没有0x么?[/quote]
看7楼红色文字[/quote]

恩。。我这个是读二进制文件中的数据装换成十六进制再转成浮点数。。所以解出来的一个十六进制结果是bf0884bd88c6ec6e,对于这种数据96180.1541071667是它应该的量级。。现在很困惑啊。。而且十六进制中间加不加空格这个很神奇,不太明白是什么原理。。能教一下我么?谢谢啦


赵4老师 2013-07-11
  • 打赏
  • 举报
回复
电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址; 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……
mujiok2003 2013-07-10
  • 打赏
  • 举报
回复
%la是c99的
www_adintr_com 2013-07-10
  • 打赏
  • 举报
回复
引用 4 楼 frankzhong_bjtu 的回复:
啊,先感谢各位,但还有问题。。我试了一下,%la没有变化,还是所有输出都是之前的那个结果,%I64x有变化了!但数据不对,bf0884bd88c6ec6e应该是96180.1541071667,但换出来是-4.67654e-005(对应的十六进制85 EA 9E E8 BE 84 08 BF);bf085f77d5bea9c5应该是96776.5103162163,但换出来的是-4.64877e-005(对应的十六进制DC A7 96 35 79 5F 08 BF)换出来的这数后三位对应原来十六进制的前三位但后面的就对不上了。。。求助大家!谢谢了!
我用 %I64x 读入的数据全都是对的, 只是顺序是颠倒的. 如果要保持顺序, 可以这样:

	char YA_HEX[20] = "bf0884bd88c6ec6e";
	double YA_Num;
	int (&x)[2] = (int(&)[2])YA_Num;

	sscanf(YA_HEX, "%08x", &x[0]);
	sscanf(YA_HEX + 8, "%08x", &x[1]);

	x[0] = htonl(x[0]);
	x[1] = htonl(x[1]);

	printf("%f", YA_Num);
虽然这样读入后 YA_Num 的内存可以对应上, 但对应的double 值并不是 96180.1541071667 而是: 21302471929538717000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000.000000
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
啊,先感谢各位,但还有问题。。我试了一下,%la没有变化,还是所有输出都是之前的那个结果,%I64x有变化了!但数据不对,bf0884bd88c6ec6e应该是96180.1541071667,但换出来是-4.67654e-005(对应的十六进制85 EA 9E E8 BE 84 08 BF);bf085f77d5bea9c5应该是96776.5103162163,但换出来的是-4.64877e-005(对应的十六进制DC A7 96 35 79 5F 08 BF)换出来的这数后三位对应原来十六进制的前三位但后面的就对不上了。。。求助大家!谢谢了!
lm_whales 2013-07-10
  • 打赏
  • 举报
回复
C输入输出函数 : 输入,没有16进制浮点数格式,输出有a,A 两种格式分别代表大写和小写 16进制浮点数。 a 格式为 [−]0xh.hhhh p±dd ,A格式为 [−]0Xh.hhhh P±dd,
mujiok2003 2013-07-10
  • 打赏
  • 举报
回复
%la 不要用%x,因为x都期待整型
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
引用 21 楼 u010936098 的回复:
[quote=引用 19 楼 frankzhong_bjtu 的回复:]
[quote=引用 18 楼 u010936098 的回复:]
[quote=引用 16 楼 frankzhong_bjtu 的回复:]

谢谢您的解答,这个结果是对的,请问一下91133977427BF740是怎么得到的?


看9楼[/quote]
恩恩,看到了,谢谢。。但我不能拿结果去计算输入啊。。。[/quote]

我的意思是说,你的那个软件的转换结果并不符合x86机器上的情况。[/quote]

额。。。我明白你的意思了。。。但这个转出来的结果的量级才是对的。。。这个程序是读二进制文件中的数据装换成十六进制再转成浮点数。。所以解出来的一个十六进制结果是bf0884bd88c6ec6e,对于这种数据96180.1541071667是它应该的量级。。现在很困惑啊。。而且十六进制中间加不加空格这个很神奇,能教一下我么?谢谢啦

橡木疙瘩 2013-07-10
  • 打赏
  • 举报
回复
引用 19 楼 frankzhong_bjtu 的回复:
[quote=引用 18 楼 u010936098 的回复:] [quote=引用 16 楼 frankzhong_bjtu 的回复:] 谢谢您的解答,这个结果是对的,请问一下91133977427BF740是怎么得到的?
看9楼[/quote] 恩恩,看到了,谢谢。。但我不能拿结果去计算输入啊。。。[/quote] 我的意思是说,你的那个软件的转换结果并不符合x86机器上的情况。
赵4老师 2013-07-10
  • 打赏
  • 举报
回复
引用 15 楼 frankzhong_bjtu 的回复:
[quote=引用 8 楼 zhao4zhong1 的回复:] Collapse AllExpand All Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript Visual Basic C# Visual C++ J# JScript Run-Time Library Reference printf Type Field Characters See Also Send Feedback The type character is the only required format field; it appears after any optional format fields. The type character determines whether the associated argument is interpreted as a character, string, or number. The types C, n, p, and S, and the behavior of c and s with printf functions, are Microsoft extensions and are not ANSI compatible. Character Type Output format a double Signed hexadecimal double precision floating point value having the form [−]0xh.hhhh p±dd, where h.hhhh are the hex digits (using lower case letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point. A double Signed hexadecimal double precision floating point value having the form [−]0Xh.hhhh P±dd, where h.hhhh are the hex digits (using capital letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point. [/color] Note If the argument corresponding to %s or %S is a null pointer, "(null)" will be printed. Note In all exponential formats, the default number of digits of exponent to display is three. Using the _set_output_format function, the number of digits displayed may be set to two, expanding to three if demanded by the size of exponent. Security Note The %n format is inherently insecure and is disabled by default; if %n is encountered in a format string, the invalid parameter handler is invoked as described in Parameter Validation. To enable %n support, see _set_printf_count_output. See Also Concepts printf, _printf_l, wprintf, _wprintf_l Send feedback on this topic to Microsoft.
是要用“%a”么,但我试了一下,没有作用。。sscanf没有给double赋值,是因为没有0x么?[/quote] 看7楼红色文字
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
引用 18 楼 u010936098 的回复:
[quote=引用 16 楼 frankzhong_bjtu 的回复:] 谢谢您的解答,这个结果是对的,请问一下91133977427BF740是怎么得到的?
看9楼[/quote] 恩恩,看到了,谢谢。。但我不能拿结果去计算输入啊。。。
橡木疙瘩 2013-07-10
  • 打赏
  • 举报
回复
引用 16 楼 frankzhong_bjtu 的回复:
谢谢您的解答,这个结果是对的,请问一下91133977427BF740是怎么得到的?
看9楼
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
引用 14 楼 zhao4zhong1 的回复:
#include <stdio.h>
int main() {
char YA_HEX[20] = "91133977427BF740";
double YA_Num;
char *p;
int i,v;

p=(char *)&YA_Num;
for (i=0;i<8;i++) {
sscanf(YA_HEX+i*2, "%2x", &v);
p[i]=(char)v;
}
printf("%.15lg", YA_Num);
return 0;
}
//96180.1541071667


我现在比较困惑的是我拿数制转换软件转出来的结果如下:


我解出的数据是bf0884bd88c6ec6e,应该得到的结果是96180.1541071667,请您看下是什么问题造成的。。谢谢了
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
引用 14 楼 zhao4zhong1 的回复:
#include <stdio.h>
int main() {
	char YA_HEX[20] = "91133977427BF740";
	double YA_Num;
	char *p;
	int i,v;

	p=(char *)&YA_Num;
	for (i=0;i<8;i++) {
		sscanf(YA_HEX+i*2, "%2x", &v);
		p[i]=(char)v;
	}
 	printf("%.15lg", YA_Num);
    return 0;
}
//96180.1541071667
谢谢您的解答,这个结果是对的,请问一下91133977427BF740是怎么得到的?
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
引用 8 楼 zhao4zhong1 的回复:
Collapse AllExpand All Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript Visual Basic C# Visual C++ J# JScript Run-Time Library Reference printf Type Field Characters See Also Send Feedback The type character is the only required format field; it appears after any optional format fields. The type character determines whether the associated argument is interpreted as a character, string, or number. The types C, n, p, and S, and the behavior of c and s with printf functions, are Microsoft extensions and are not ANSI compatible. Character Type Output format a double Signed hexadecimal double precision floating point value having the form [−]0xh.hhhh p±dd, where h.hhhh are the hex digits (using lower case letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point. A double Signed hexadecimal double precision floating point value having the form [−]0Xh.hhhh P±dd, where h.hhhh are the hex digits (using capital letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point. [/color] Note If the argument corresponding to %s or %S is a null pointer, "(null)" will be printed. Note In all exponential formats, the default number of digits of exponent to display is three. Using the _set_output_format function, the number of digits displayed may be set to two, expanding to three if demanded by the size of exponent. Security Note The %n format is inherently insecure and is disabled by default; if %n is encountered in a format string, the invalid parameter handler is invoked as described in Parameter Validation. To enable %n support, see _set_printf_count_output. See Also Concepts printf, _printf_l, wprintf, _wprintf_l Send feedback on this topic to Microsoft.
是要用“%a”么,但我试了一下,没有作用。。sscanf没有给double赋值,是因为没有0x么?
赵4老师 2013-07-10
  • 打赏
  • 举报
回复
#include <stdio.h>
int main() {
	char YA_HEX[20] = "91133977427BF740";
	double YA_Num;
	char *p;
	int i,v;

	p=(char *)&YA_Num;
	for (i=0;i<8;i++) {
		sscanf(YA_HEX+i*2, "%2x", &v);
		p[i]=(char)v;
	}
 	printf("%.15lg", YA_Num);
    return 0;
}
//96180.1541071667
赵4老师 2013-07-10
  • 打赏
  • 举报
回复
#include <stdio.h>
int main() {
	char YA_HEX[20] = "bf0884bd88c6ec6e";
	double YA_Num;
	char *p;
	int i,v;

	p=(char *)&YA_Num;
	for (i=0;i<8;i++) {
		sscanf(YA_HEX+i*2, "%2x", &v);
		p[i]=(char)v;
	}
 	printf("%.15lg", YA_Num);
    return 0;
}
//2.13024719295387e+226
//
www_adintr_com 2013-07-10
  • 打赏
  • 举报
回复
引用 10 楼 frankzhong_bjtu 的回复:
[quote=引用 5 楼 adlay 的回复:] [quote=引用 4 楼 frankzhong_bjtu 的回复:] 啊,先感谢各位,但还有问题。。我试了一下,%la没有变化,还是所有输出都是之前的那个结果,%I64x有变化了!但数据不对,bf0884bd88c6ec6e应该是96180.1541071667,但换出来是-4.67654e-005(对应的十六进制85 EA 9E E8 BE 84 08 BF);bf085f77d5bea9c5应该是96776.5103162163,但换出来的是-4.64877e-005(对应的十六进制DC A7 96 35 79 5F 08 BF)换出来的这数后三位对应原来十六进制的前三位但后面的就对不上了。。。求助大家!谢谢了!
我用 %I64x 读入的数据全都是对的, 只是顺序是颠倒的. 如果要保持顺序, 可以这样:

	char YA_HEX[20] = "bf0884bd88c6ec6e";
	double YA_Num;
	int (&x)[2] = (int(&)[2])YA_Num;

	sscanf(YA_HEX, "%08x", &x[0]);
	sscanf(YA_HEX + 8, "%08x", &x[1]);

	x[0] = htonl(x[0]);
	x[1] = htonl(x[1]);

	printf("%f", YA_Num);
虽然这样读入后 YA_Num 的内存可以对应上, 但对应的double 值并不是 96180.1541071667 而是: 21302471929538717000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000.000000[/quote] 大神,你是怎么看内存对应上的?我拿vc 调试看的内容是这个 然后你那个结果是我拿数制转换的软件看bf 08 84 bd 88 c6 ec 6e转成2.13024719295387E226, bf0884bd88c6ec6e转成96180.1541071667。。。这个问题很奇怪啊。。。 [/quote] 在 VC 的调试状态, 断到 YA_Num 已经读取以后, 打开调试->窗口->内存 XX, 然后在地址栏输入 &YA_Num
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
引用 9 楼 u010936098 的回复:

int main()
{

unsigned __int64 udata;
double fdata;
unsigned char * ptr = (unsigned char *)&fdata;

fdata = 96180.1541071667;
printf("\n%.10f\n", fdata);
printf("%02X%02X%02X%02X%02X%02X%02X%02X\n", ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],ptr[6],ptr[7]);

fdata = 96776.5103162163;
printf("\n%.10f\n", fdata);
printf("%02X%02X%02X%02X%02X%02X%02X%02X\n", ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],ptr[6],ptr[7]);

}


输出结果为:

96180.1541071667
91133977427BF740

96776.5103162163
3A56412A88A0F740


谢谢你的解答,不过我是要拿十六进制转double,而且你转的十六进制好像不是很对
frankzhong_bjtu 2013-07-10
  • 打赏
  • 举报
回复
引用 5 楼 adlay 的回复:
[quote=引用 4 楼 frankzhong_bjtu 的回复:]
啊,先感谢各位,但还有问题。。我试了一下,%la没有变化,还是所有输出都是之前的那个结果,%I64x有变化了!但数据不对,bf0884bd88c6ec6e应该是96180.1541071667,但换出来是-4.67654e-005(对应的十六进制85 EA 9E E8 BE 84 08 BF);bf085f77d5bea9c5应该是96776.5103162163,但换出来的是-4.64877e-005(对应的十六进制DC A7 96 35 79 5F 08 BF)换出来的这数后三位对应原来十六进制的前三位但后面的就对不上了。。。求助大家!谢谢了!


我用 %I64x 读入的数据全都是对的, 只是顺序是颠倒的.
如果要保持顺序, 可以这样:


char YA_HEX[20] = "bf0884bd88c6ec6e";
double YA_Num;
int (&x)[2] = (int(&)[2])YA_Num;

sscanf(YA_HEX, "%08x", &x[0]);
sscanf(YA_HEX + 8, "%08x", &x[1]);

x[0] = htonl(x[0]);
x[1] = htonl(x[1]);

printf("%f", YA_Num);


虽然这样读入后 YA_Num 的内存可以对应上, 但对应的double 值并不是 96180.1541071667 而是:
21302471929538717000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000.000000[/quote]

大神,你是怎么看内存对应上的?我拿vc 调试看的内容是这个


然后你那个结果是我拿数制转换的软件看bf 08 84 bd 88 c6 ec 6e转成2.13024719295387E226,
bf0884bd88c6ec6e转成96180.1541071667。。。这个问题很奇怪啊。。。
加载更多回复(4)

65,202

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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