C语言数据类型的探索(2)

1、怎么判断两个浮点数是否相等?

以下代码输出结果是什么

int main(int argc, char *argv[])
{
double a = 3.14;
float b = a;
if ((float)a == b)
{
printf("Xiyou");
}
if (a != b)
{
printf("LinuxGroup\n");
}
return 0;
}

//输出为:XiyouLinuxGroup

这里说明float a==float b,而double a !=float b,那是为什么呢?

首先

我们来了解float和double的存储方式,与整型不同

SEM型,float占32位4个字节,double占64位8个字节。

分别为符号位、指数、尾数

在这里插入图片描述

如:写出十进制数5.75的余127码(单精度)表示法。

a.符号为正,S=0。

b.十进制转二进制:5.75=(101.11)2进制

c.规范化:(101.11)(2进制)=(1.0111)*2^2(2的平方)

d.E=2+127=129=(10000001)2,M=0111。

M右边加19个0使之变成23位

表示如下

S         E                      M

0      10000001          0111000000000000000000

存储在计算机中的数字是01000000101110000000000000000000

其次

  • float的精度误差在1e-6;
    所以要判断一个float型数:if(fabs(f) < 1e-6);
    若满足,则相等
  • double精度误差在1e-15
    要判断一个double型数:if(fabs(f) < 1e-15);
    若满足,则相等

1e-6表示1乘以10的负6次方。

Math.abs(x)<1e-6其实相当于x==0 

1e-6(也就是0.000001)叫做epslon,用来抵消浮点运算中因为误差造成的相等无法判断的情况。它通常是一个非常小的数字(具体多小要看你的运算误差)

比如说因为精度误差,用十进制举例,我们要算1/3+1/3+1/3==1(从数学上说,肯定相等),但是因为精度问题,等号左边算出来是0.3333333+0.3333333+0.3333333=0.9999999,

存在了误差,右边是1.0000000,那么如果直接用==,返回false,我们希望它被视作相等。那么就要两数相减取绝对值小于epslon的办法。

而float和double的精度误差要求不同,所以才会出现题目中的情况。

double的要求更高,所以当double a转为float能与b相等,但若用 (double )b和double a判断,则不能相等。

2、隐式类型转换

下面的代码输出的结果是什么呢?

int i;
int main(int argc, char *argv[])
{
i--;
if (i > sizeof(i))
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}


//输出:>

这里int i为全局变量未赋值,初始化默认为0。i--后i变成-1。

sizeof(i)=4。此时不是-1与4的直接比较。

而是

sizeof结果为long unsigned int,是无符号型。

无符号型和有符号型比较,全都转为无符号型比较

而将-1转为无符号

1000000 00000000 00000000 00000001

此时开头的1不再表示符号

显然大于sizeof(i)=4。

(补码的用途?)

这里用到隐式类型转换的知识

进行算术运算(加、减、乘、除、取余以及符号运算)时,不同类型数据必须转换成同 一类型的数据才能运算,算术转换原则为:

   整型提升:对于所有比int小的类型,包括char, signed char, unsigned char, short, unsigned short,首先会提升为int类型。

    在进行运算时,以表达式中最长类型为主,将其他类型位据均转换成该类型,如:

(1)若运算数中有double型或float型,则其他类型数据均转换成double类型进行运算。

(2)若运算数中最长的类型为long型.则其他类型数均转换成long型数。

(3)若运算数中最长类型为int型,则char型也转换成int型进行运算。算术转换是在运算过程中自动完成的。

    特别注意的是有符号和无符号之间的转换:

    包含long与unsigned int,32位机器上都是4字节,所以均转换为unsigned long.

    包含signed与unsigned int,signed会转换为unsigned。如果int恰好为负数,其结果为对unsigned取值个数求模的结果。比如将-1赋给8位的unsigned char,呢么结果就是255(-1对256取模后的值)。unsigned char取值范围0~255。

3、数据溢出

下面代码段将打印出多少个‘=’?

int main(int argc, char *argv[]) {
for (unsigned int i = 3; i >= 0; i--)
putchar('=');
}


//会不停地输出=

因为是unsigned int 型,当i=0时,再-1,变成4294967295

执行下面的代码段,会输出什么?

int main(int argc, char *argv[]) {
char ch = 255;

int d = 'a' + 1;
printf("%d %d", ch, d);
}


//输出结果:-1 98

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值