[C语言]解析bool, float

冬戎r 2024-10-25 11:35:02 阅读 97

一、BOOL

1、C语言<code>bool详解

bool是C语言中的一个关键字,用于声明布尔类型的变量。布尔类型只有两个可能的值:truefalse。在C99标准之前,C语言并没有内置的布尔类型,人们通常使用int类型,并用0表示false,非0(通常是1)表示trueC99标准引入了bool类型,以及头文件<stdbool.h>,它定义了booltruefalse

2、bool的用法和定义 

        要使用bool类型,首先需要包含头文件<stdbool.h>然后,你可以像声明其他类型的变量一样声明bool类型的变量:

#include <stdbool.h>

bool isHappy = true;

bool isSad = false;

3、bool的基本作用

   bool类型的主要作用是提供一种更直观、更易于理解的方式来表示逻辑值。在编写条件语句时,使用bool类型的变量可以使代码更加清晰和易于理解。

4、bool与其他类型的转换

        在需要时,bool类型的值可以隐式地转换为int类型,其中false转换为0true转换为1。但是,将int类型转换为bool类型时,0会被转换为false,任何非0的值都会被转换为true

5、使用bool的注意事项

不要将bool类型的变量与整数类型混淆,尽管它们之间可以转换。在编写条件语句时,直接使用bool类型的变量作为条件,而不要与truefalse进行比较,例如if (isHappy)而不是if (isHappy == true)。在一些旧的C编译器或环境中,可能不支持bool类型。在这种情况下,你可以使用int类型并遵循相同的逻辑约定。

6、拓展:bool类型与其“零值”比较

        在布尔逻辑的语义中,零值被视为“假”(FALSE),而任何非零值都被视为“真”(TRUE)。值得注意的是,TRUE的具体数值并没有统一的标准,它依赖于具体的编程语言或环境。例如,在Visual C++中,TRUE被定义为1,而在Visual Basic中,TRUE则被定义为-1。

        重要的是要理解,bool类型变量的本质是一个布尔表达式,用于表示与“零值”(即FALSE)的比较结果。因此,在if语句中直接使用bool类型的变量作为条件表达式,无需显式地与其“零值”进行比较。正确的if语句用法如下:

bool b;

// 假设b已被赋予某个值

if (b) {

// 如果b为真(非零),则执行此处代码

...

}

// 使用逻辑非操作符"!"来检查b是否为假(零值)

if (!b) {

// 如果b为假(零值),则执行此处代码

...

}

二、FLOAT

1、float的定义和用途

        float关键字用于声明一个单精度浮点变量,它能够存储带有小数的数值,且数值范围相对较广。在C语言中,float类型通常占用4个字节(32位)的内存空间,其中1位用于符号位,8位用于指数位,而剩下的23位则用于尾数位。

2、float的基本使用

        在C语言中,使用float关键字定义变量时,需要在变量名后加上“f”或“F”后缀,以明确表示这是一个float类型的常量。例如:

float a = 3.14f;

//如果不加“f”或“F”后缀,编译器可能会将其视为double类型的常量,进而可能引发类型不匹配的警告或错误。

3、float的精度问题

        float精度问题的根本原因在于计算机内部使用二进制来表示浮点数,而很多十进制小数无法完全用二进制精确表示。此外,float类型在存储时遵循IEEE 754标准,该标准将32位分为符号位(1位)、指数位(8位)和尾数位(23位),这种表示方式也限制了float的精度。

      具体来说,尾数位用于表示浮点数的小数部分,但由于只有23位,因此只能精确表示一定范围内的数字。对于超出这个范围的数字,计算机将进行舍入操作,以找到最接近的可表示数字,从而导致精度损失。

4、精度问题的举例

1、0.1无法精确表示

        在十进制中,0.1是一个简单的数字,但在二进制中,它无法精确表示。当我们尝试将0.1存储为float类型时,计算机会将其转换为最接近的二进制分数,从而导致精度损失。例如:

float a = 0.1f;

// 输出可能不是0.1,而是类似0.100000024的近似值

2、浮点数相加产生精度损失:

        当我们将两个浮点数相加时,如果它们的小数部分无法精确表示,那么相加的结果也可能出现精度损失。例如:

float b = 0.2f;

float c = a + b; // a为上面例子中定义的0.1f

// c可能不是0.3,而是类似0.300000012的近似值

3、浮点数相加产生精度损失:

        在进行循环或条件判断时,如果涉及到浮点数的比较,可能会因为精度问题而导致逻辑错误。例如,在判断两个浮点数是否相等时,由于精度损失,直接使用==运算符往往不是最佳选择。

5、拓展:float类型与“零值”比较

  float​类型对应的“零值”并不是0.0​,这是由于浮点类型会丢失精度。此外,float​类型不能用==​或者!=​进行比较,只能使用<=​和>=​构建一个排除其“零值”的区间进行比较。

        如仅分析理论,在c语言的float.h​或c++的cfloat​文件中,提供了一个FLT_EPSILON​常量。该常量为1.192092896e-07F​,表示1与大于的第一个(或最小)单精度浮点数之差,即理论最小正单精度浮点数。根据该常量,我们可以写出以下语句:

#include<float.h>

// c++ 为 #include<cfloat>

...

float a = 某浮点数;

...

// 为"零值"

if((a >= -FLT_EPSILON) && (a <= FLT_EPSILON)){

...

}

// ---- and ----

// 不为“零值”

if((a <= -FLT_EPSILON) || (a >= FLT_EPSILON)){

...

}

        此外,double类型也有同样的极限常量,为DBL_EPSILON​,同样可从float.h​或cfloat​文件引入,在此不做赘述。

       实际过程中,需要具体情况具体分析,还要考虑读数的测量误差等问题,而非简单用数学极限去排除“零值”。比如一个表示测量水桶水位的浮点读数,假设当水桶水空的时候,再往里面加水,此时我们如果用FLT_EPSILON​去比较就不太合理了。

6、拓展:指针变量与其“零值”比较

指针变量的零值是“空”(记为NULL​),在C语言和C++中,NULL​的定义并不相同。

//在C语言中,习惯将NULL定义为void*指针值0:

#define NULL (void*)0

//在C++中,NULL却被明确定义为整常数0:

// wchar.h中定义NULL的源码

#ifndef NULL

#ifdef __cplusplus

#ifndef _WIN64

#define NULL 0

#else

#define NULL 0LL

#endif /* W64 */

#else

#define NULL ((void *)0)

#endif

#endif

        在C++11以下的版本中,指针变量与其“零值”的比较,实质上就是指针变量与NULL​的比较,而在C++11以上的版本中,由于nullptr的引入,统一了C语言和C++的差异,如下:

//----------------C++ 11 以下--------------------

char* c;

if(c == NULL){

...

}

// ---- and ----

if(c != NULL){

...

}

//----------------C++ 11 以上--------------------

char* c;

if(c == nullptr){

...

}

// ---- and ----

if(c != nullptr){

...

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。