比较两个浮点数完全不用这么麻烦,但本人只是想深入了解一下memcmp的功能。
本人发现可以用memcmp比较浮点数,但输出结果有问题:
本人发现可以用memcmp比较浮点数,但输出结果有问题:
#include <stdio.h> #include <string.h> int main( void ) { double a = 1.0; double b = 2.0; double *aPtr, *bPtr; aPtr = &a; bPtr = &b; printf( "%d", memcmp( aPtr, bPtr, 8 ) ); return 0; }
这个程序结果是1,但1.0<2.0不应该是-1吗?
解决方案:37分
解决这个问题需要了解两个方面的知识
1、memcmp函数的意义
2、double数据类型在内存中的表示
—
1、memcmp函数的意义
比较前n个字节的大小。
—
2、double数据类型在内存中的表示
为了更好地理解,下面把double类型的 1.0 和 2.0 在内存中的表示以十六进制的形式列出来
1.0 == 00-00-00-00-00-00-F0-3F
2.0 == 00-00-00-00-00-00-00-40
从上面的内存表示可以很容易知道为什么1.0和2.0用memcmp函数比较之后反而是1.0大了。
那么接下来的问题就是1.0和2.0为什么在内存中就是那么表示的。
(1)先将1.0和2.0分别用二进制的科学计数法表示
1.0 == 1.0乘以(2的0次方)
2.0 == 1.0乘以(2的1次方)
* 规定 double 在内存中以三个部分存储:符号、阶码、尾数
* 符号占1位、阶码占11位、尾数点52位
* 由于尾数的小数点之前都是数字1,所以规定小数点之前的数字1不必存储,也就是说尾数只需要存储小数点之后的数值即可
* 正数的符号为0 负数的符号为1
* 规定阶码存储时需要加上1023
所以,1.0的阶码0,加上1023之后是1023,二进制表示为 0111 1111 111
2.0的阶码1,加上1023之后是1024,二进制表示为 1000 0000 000
由于 1.0 和 2.0 的符号位、尾数都是0
所以, 1.0 == 0(符号位) 0111 1111 111(十一位阶码) (此处省略五十二位尾数0)
2.0 == 0(符号位) 1000 0000 000(十一位阶码) (此处省略五十二位尾数0)
1、memcmp函数的意义
2、double数据类型在内存中的表示
—
1、memcmp函数的意义
比较前n个字节的大小。
—
2、double数据类型在内存中的表示
为了更好地理解,下面把double类型的 1.0 和 2.0 在内存中的表示以十六进制的形式列出来
1.0 == 00-00-00-00-00-00-F0-3F
2.0 == 00-00-00-00-00-00-00-40
从上面的内存表示可以很容易知道为什么1.0和2.0用memcmp函数比较之后反而是1.0大了。
那么接下来的问题就是1.0和2.0为什么在内存中就是那么表示的。
(1)先将1.0和2.0分别用二进制的科学计数法表示
1.0 == 1.0乘以(2的0次方)
2.0 == 1.0乘以(2的1次方)
* 规定 double 在内存中以三个部分存储:符号、阶码、尾数
* 符号占1位、阶码占11位、尾数点52位
* 由于尾数的小数点之前都是数字1,所以规定小数点之前的数字1不必存储,也就是说尾数只需要存储小数点之后的数值即可
* 正数的符号为0 负数的符号为1
* 规定阶码存储时需要加上1023
所以,1.0的阶码0,加上1023之后是1023,二进制表示为 0111 1111 111
2.0的阶码1,加上1023之后是1024,二进制表示为 1000 0000 000
由于 1.0 和 2.0 的符号位、尾数都是0
所以, 1.0 == 0(符号位) 0111 1111 111(十一位阶码) (此处省略五十二位尾数0)
2.0 == 0(符号位) 1000 0000 000(十一位阶码) (此处省略五十二位尾数0)
写成十六进制的形式为 1.0 == 3F-F0-00-00-00-00-00-00
2.0 == 40-00-00-00-00-00-00-00
最后,由于一般计算机中内存以小端存储,也就是数值的高字节反而是放在后面的。
所以在内存中的表示为 1.0 == 00-00-00-00-00-00-F0-3F
2.0 == 00-00-00-00-00-00-00-40