浮点数与0比较

前言

在平时的编写代码的过程中,细心的小伙伴们不难发现浮点数的精度的都有些不准确,如下图:
在这里插入图片描述
该篇文章将讲解如应对这种问题。

一、浮点数与0的比较

浮点数在内存中存储,并不想我们想的,是完整存储的,在十进制转化成为二进制,是有可能有精度损失的。
注意这里的损失,不是一味的减少了,还有可能增多。浮点数本身存储的时候,在计算不尽的时候,会“四舍五入

#include<stdio.h>
#include <stdio.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 ((x - 0.9) == y) {
		printf("you can see me!\n");
	}
	else {
		printf("oops\n");
	}
	system("pause");
	return 0;
}

在这里插入图片描述
正常应该打印“”you can see me!“”,但实际两数并不相等,因为浮点数精度有缺失。
结论:因为精度损失问题,两个浮点数,绝对不能使用==进行相等比较.
那么两个浮点数该如何比较呢?
应该进行范围精度比较

//伪代码
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;
}

注:DBL_EPSILON是最小误差。

总结

感谢大家阅读本文章!。

<think>根据提供的引用资料,浮点数在计算机中存在精度问题,因此不能直接使用等号或不等号比较。常见的做法是比较差值或使用特定工具。 引用[1]提到PHP中浮点数比较时,通常比较其差值的绝对值是否小于一个很小的阈值(如$10^{-6}$)。引用[2]展示了Shell中通过bc命令处理浮点数比较。引用[3]则用JavaScript的parseFloat转换为浮点数后再比较。 通用方法: 1. 转为相同类型:将整数转为浮点数或反之(但整数转浮点可能损失精度)。 2. 差值比较:对于两个数$a$和$b$,若$|a - b| < \epsilon$($\epsilon$为极小正数,如$10^{-6}$),则视为相等。 3. 利用工具:如Shell用bc,Python用math.isclose等。 注意事项: - 不同语言实现方式不同。 - 阈值$\epsilon$的选择需根据实际精度要求。 **示例代码(Python)**: ```python def float_compare(a, b, epsilon=1e-6): if abs(a - b) < epsilon: return "相等" elif a > b: return "a > b" else: return "a < b" print(float_compare(0.1 + 0.2, 0.3)) # 输出"相等" ``` §§相关问题§§ 1. 为什么浮点数在计算机中表示不精确? 2. 如何在Java中比较浮点数? 3. 编程中处理浮点数比较的最佳实践是什么? </think>### 浮点数整数比较大小的方法 在编程中比较浮点数和整数时,由于浮点数存在精度问题,直接比较可能导致错误结果。以下是核心方法和注意事项: #### 1. **类型转换后比较**(推荐) 将整数显式转换为浮点数比较,避免隐式转换错误: ```javascript // JavaScript示例(引用[3]方法) let num = 15; // 整数 let floatNum = 15.0; // 浮点数 if (parseFloat(num) === parseFloat(floatNum)) { console.log("相等"); } ``` **原理**: 通过`parseFloat()`/`parseInt()`或语言等效函数统一类型,消除二进制存储差异(如整数15存储为`1111`,浮点数15.0可能存储为`1.5e1`)。 #### 2. **阈值比较法**(通用方案) 比较两数差值的绝对值是否小于可接受误差: ```python # Python示例 def is_equal(a, b, epsilon=1e-6): return abs(a - b) < epsilon print(is_equal(3, 3.0000001)) # 输出 True ``` **关键点**: - 阈值$\epsilon$根据精度需求设定(科学计算常用$10^{-9}$,普通应用$10^{-6}$) - 适用于所有支持浮点运算的语言(引用[1]原理) #### 3. **语言特定工具** - **Shell**:通过`bc`命令处理(引用[2]方案): ```bash if [ $(echo "3.14 > 3" | bc) -eq 1 ]; then echo "浮点数更大" fi ``` - **PHP**:使用`abs($a-$b) < EPSILON`(引用[1]) - **Java**:`Math.abs(a - b) < 1e-9` #### ⚠️ 禁止直接比较的情况 ```javascript // 错误示例(可能失败) 0.1 + 0.2 === 0.3 // 返回false(实际0.1+0.2=0.30000000000000004) ``` #### 比较操作最佳实践 | 操作 | 正确方法 | 错误示例 | |------------|-----------------------------------|------------------| | 相等判断 | `abs(a-b) < ε` | `a == b` | | 大小比较 | `a > b + ε` 或 `a - b > ε` | `a > b` | | 范围判断 | `x > (low - ε) && x < (high + ε)`| 直接比较边界 | > **底层原理**:浮点数遵循IEEE 754标准,用二进制分数表示十进制数时可能产生无限循环小数(如$0.1_{10} = 0.0001100110011..._2$),导致精度丢失[^1]。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1无名之辈1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值