关于C语言浮点数正0和负0那点破事

是这样的:

众所周知,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×2exp127×{1,sign=01,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×2126

那么问题来了,这么搞,可就有正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.0V2F(0x80000001)/2.0这种除成0了它会变成正0还是负0。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值