float类型与"零值"的比较
浮点数的存储
浮点数在内存中存储,并不想我们想的是完整存储的
在十进制转化成为二进制,是有可能有精度损失的
注意
这里的损失,不是一味的减少了,还有可能增多
浮点数本身存储的时候,在计算不尽的时候,会“四舍五入”或者其他策略
int main() { double x = 3.6; printf("%.50f\n", x); system("pause"); return 0; }
int main() { double x = 1.0; double y = 0.1; printf("%.50f\n", x - 0.9); printf("%.50f\n", y); if ((x - 0.9) == y) { printf("you can see me!\n"); } else { printf("oops\n"); } system("pause"); return 0; }
解决方案:进行范围精度比较
//伪代码 if((x-y) > -精度 && (x-y) < 精度) { //TODO } //伪代码-简洁版 if(fabs(x-y) < 精度) {//fabs是浮点数求绝对值 //TODO }
精度
自己设置?后面如果有需要,可以试试,通常是宏定义
使用系统精度?暂时推荐
#include<float.h> //使用下面两个精度,需要包含该头文件 DBL_EPSILON //double 最小精度 FLT_EPSILON //float 最小精度 //代码调整后 #include <stdio.h> #include <math.h> //必须包含math.h,要不然无法使用fabs #include <float.h> //必须包含,要不然无法使用系统精度 #include <windows.h> int main() { double x = 1.0; double y = 0.1; printf("%.50f\n", x - 0.9); printf("%.50f\n", y); if (fabs((x - 0.9) - y) < DBL_EPSILON) { //原始数据是浮点数,我们就用DBL_EPSILON printf("you can see me!\n"); } else { printf("oops\n"); } system("pause"); return 0; }
定义
//两个精度定义 #define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */ #define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
XXX_EPSILON 是最小误差 , 是: XXX_EPSILON + n 不等于 n 的最小的正数。
EPSILON 这个单词翻译过来是 'ε' 的意思,数学上,就是极小的正数 ---- 来自百度
//最终代码 #include <stdio.h> #include <math.h> #include <float.h> #include <windows.h> int main() { double x = 0.00000000000000000000001; //if (fabs(x-0.0) < DBL_EPSILON){ //写法1 //if (fabs(x) < DBL_EPSILON){ //写法2 if(x > -DBL_EPSILON && x < DBL_EPSILON) { //书中写法 printf("you can see me!\n"); } else { printf("oops\n"); } system("pause"); return 0; }
关于需不需要取等号
x > -DBL_EPSILON && x < DBL_EPSILON: 为何不是>= && <= 呢?
个人看法:XXX_EPSILON是最小误差,是:XXX_EPSILON+n不等于n的最小的正数
XXX_EPSILON+n不等于n的最小的正数:
有很多数字+n都可以不等于n,但是XXX_EPSILON是最小的
but,XXX_EPSILON依旧是引起不等的一员
XXX_EPSILON+n不等于n的最小的正数:
有很多数字+n都可以不等于n,但是XXX_EPSILON是最小的
but,XXX_EPSILON依旧是引起不等的一员
Bool(布尔)类型与"零值"的比较
深入理解C 中 bool
C语言有没有bool类型?
c99之前,主要是c90/c89是没有的
目前大部分书,都是认为没有的
因为书,一般都要落后于行业
但是c99引入了_Bool类型
你没有看错,_Bool就是一个类型
不过在新增头文件stdbool.h中,被重新用宏写成了 bool,为了保证C/C++兼容性
//测试代码1 #include <stdio.h> #include <stdbool.h> //没有这个头文件会报错,使用新特性一定要加上 #include <windows.h> int main() { bool ret = false; ret = true; printf("%d\n", sizeof(ret)); //vs2013 和 Linux中都是1 system("pause"); return 0; }
//查看源码 /* stdbool.h standard header */ //stdbool.h #ifndef _STDBOOL #define _STDBOOL #define __bool_true_false_are_defined 1 #ifndef __cplusplus #define bool _Bool //c99中是一个关键字哦,后续可以使用bool #define false 0 //假 #define true 1 //真
理论上,表示真假,需要一个bit就够了
不过这个问题,还是要取决于编译器的理解
vs2013中认为是1个字节
but
int main() { //在vs中,光标选中BOOL,单击右键,可以看到转到定义,就能看到BOOL是什么 BOOL ret = FALSE; ret = TRUE; printf("%d\n", sizeof(ret)); //输出结果是4,因为在源代码中,是这么定义的:typedef int BOOL; system("pause"); return 0; }
这是Microsoft自己搞的一套BOOL值。在vs中转到BOOL对应的头文件,翻到最上面,就能看到微软的版权信息。可以通过编译,但可移植性差。
总结:
1. 优先使用c90,就是我们之前以及后面一直用的方式
2. 万一非得使用bool,推荐c99标准,不推荐MS自定义