是这样的:
众所周知,C语言当中,单精度浮点数是这样表示的:
符号位 s i g n sign sign为0,则为正;否则为负。
- 其中,阶码 e x p exp exp在
[1,0xfe]
之间时,它的值为:v a l = ( 1. a 23 a 22 a 21 . . . a 1 ) b i n a r y × 2 e x p − 127 × { 1 , s i g n = 0 − 1 , s i g n = 1 val = (1.a_{23}a_{22}a_{21}...a_1)_{binary} \times 2^{exp-127} \times \left \{ \begin{matrix} 1,sign = 0 \\ -1,sign = 1 \end{matrix} \right. val=(1.a23a22a21...a1)binary×2exp−127×{1,sign=0−1,sign=1
- 然后, e x p = 0 x f f exp = 0xff exp=0xff时:
v a l = { ± i n f , a 23 a 22 a 21 . . . a 1 = 0 , 正负取决于符号 N a N , a 23 a 22 a 21 . . . a 1 ≠ 0 val = \left \{ \begin{matrix}\pm inf, a_{23}a_{22}a_{21}...a_{1}= 0, 正负取决于符号 \\ \\ NaN, a_{23}a_{22}a_{21}...a_{1} \neq 0\end{matrix} \right. val=⎩ ⎨ ⎧±inf,a23a22a21...a1=0,正负取决于符号NaN,a23a22a21...a1=0
- 然后, e x p = 0 exp=0 exp=0时:
v a l = 0. a 23 a 22 a 21 . . . a 1 × 2 − 126 val = 0.a_{23}a_{22}a_{21}...a_{1} \times 2^{-126} val=0.a23a22a21...a1×2−126
那么问题来了,这么搞,可就有正0和负0了呀。
那么C语言会怎么处理?是让两者同时存在,还是把V2F(0x80000000u)
(这里 整成其他值?V2F
表示32位二进制向量解释为单精度浮点数后的值)
然后我就跑了如下代码;
#include <stdio.h>
int main()
{
unsigned *p = malloc(sizeof(unsigned));
float *fp = p;
*p = 0x80000000u;
unsigned *p2 = malloc(sizeof(unsigned));
float *fp2 = p2;
*p2 = 0u;
printf("f1: %e\n",(*fp));
printf("f2: %e\n",(*fp2)); // 用%e是因为如果浮点数过小,%f统统显示0,看不出来信息。
printf("equal: %d\n",(*fp2)==(*fp));
free(p2);
free(p);
return 0;
}
GCC版本:4.9.2,没有优化(可能自带O1优化?不管了,问题不大)。
然后输出:
f1: -0.000000e+000
f2: 0.000000e+000
equal: 1
实验结果表明,C语言允许浮点数正0负0同时存在,且二者相等。
接下来大家可以试试双精度、算术运算等,尤其是比如V2F(0x00000001)/2.0
和V2F(0x80000001)/2.0
这种除成0了它会变成正0还是负0。