C、C++中出现nan、inf原因

本文详细解析了在C/C++编程中,nan(not a number)和inf(infinity)的产生原因,包括对负数开方、求对数,0/0,0*inf等操作导致的nan,以及超出浮点数表示范围导致的inf。同时介绍了如何使用math.h库中的宏来判断变量是否为nan或inf。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在数据处理输入输出时,极有可能遇到数据读入空值(极大、极小)、运算中分母为0或0.0,对0取对数等操作,这将产生nan或inf的产生。这篇博文旨在分析C/C++产生nan和inf的操作及判断是否有nan或inf产生。

NAN的产生原因

nan: not a number,表示“无效数字”。

  • 1、对负数开方,如:−1.0‾‾‾‾‾√;
  • 2、对负数求对数,如:log(−1.0);
  • 3、0.0 / 0.0;
  • 4、0.0 * inf;
  • 5、inf / inf;
  • 6、nf-inf这些操作都会得到nan。
    (0 / 0会产生操作异常;0.0 / 0.0不会产生操作异常,而是会得到nan);

注意:nan是无序的(unordered),无法对其进行逻辑运算。它不大于、小于或等于任何数(包括它自己),将<,>,<=,和>=作用于nan产生一个exception。得到nan时就查看是否有非法操作,如果表达式中含有nan,那么表达式的结果为nan。

INF的产生原因

INF:infinite,表示“无穷大”。
超出浮点数的表示范围(溢出,即阶码部分超过其能表示的最大值)。

注意:+inf大于任何数(除了它自己和nan),-inf小于任何数(除了它自己和nan),得到inf时就查看是否有溢出或者除以0。inf在C语言表达式中就表示数学里无限的概念,如1.0/inf等于0.0,并可以与其他浮点数进行比较的(可以参与<=、>+、==、!=等运算)。

nan和inf的判断

下面几个宏即包含在math.h头文件,可用于判断一个表达式的结果是否为inf、nan或其他。使用时包括include<math.h>。

int isfinite(x);
int isnormal(x);
int isnan(x);
int isinf(x);

使用方法,及结果:

    int isfinite(x) ,判断x是否有限,是返回1,其它返回0;
    int isnormal(x),判断x是否为一个数(非inf或nan),是返回1,其它返回0;
    int isnan(x),当x时nan返回1,其它返回0;
    int isinf(x) ,当x是正无穷是返回1,当x是负无穷时返回-1,其它返回0。有些编译器不区分。

测试

产生nan或inf的操作,使用库函数(宏)判断,直接参考原文。

原文:https://blog.csdn.net/wokaowokaowokao12345/article/details/72846436/

### STM32中导致`-nan`出现的原因及解决方法 #### 1. `-nan` 的含义 在C/C++编程环境中,`-nan` 表示“Not a Number”,通常是在浮点运算过程中出现了无法定义的结果。这种现象可能是由于非法操作引起的,例如除以零、无穷减去无穷等[^1]。 #### 2. 导致`-nan`的主要原因 以下是可能导致STM32程序中出现`-nan`的一些常见情况: - **溢出或下溢** 当浮点数的值超出了其能够表示的有效范围时,可能会返回`-nan` 或 `inf`(正无穷)。这通常是由于不合理的数值增长或缩小造成的。 - **非法算术操作** 如果进行了诸如 `sqrt(-1)` 这样的非法操作,则会触发`-nan` 结果。这是因为平方根函数不允许接受负实数作为输入参数。 - **数据类型转换错误** 在某些情况下,如果将一个超出有效范围的数据强制转换成较小类型的浮点数,也可能引发此类问题。例如,在处理大量数据并将其压缩至较低精度格式 (如从 float 转换为 half-float) 时,容易丢失重要信息而导致异常结果[^2]。 - **内存损坏或未初始化变量** 使用未经适当初始化或者被意外覆盖掉内容的变量参与计算也会造成不可预测的行为,其中包括生成`-nan` 值[^4]。 #### 3. 解决方案 针对以上提到的各种可能性,可以采取以下措施来预防和修复`-nan`问题的发生: - **检查所有涉及数学运算的部分** 审查代码中的每一个表达式是否有潜在的风险因素存在;特别是那些涉及到复杂公式的部分更应仔细核查是否存在任何违反基本规则的操作行为。 - **合理控制数值规模** 对于可能出现极端变化的大数或小数序列,提前设定好界限条件以防它们突破系统所能承受的最大限度之外。 - **选用合适的优化级别** 高度依赖硬件特性的编译器选项有时会影响最终产物的表现形式——尤其是在混合使用不同宽度规格化后的数字对象之间相互作用之时尤为明显。因此建议按照实际需求调整相应的设置项(O0~O3),必要时候关闭特定指令集支持以便获得更加稳定的性能表现。 - **更新固件库及相关驱动程序** 如遇到与具体型号密切关联的技术难题,则应及时查阅官方文档说明以及最新版本发布日志记录寻找对应补丁包下载安装地址链接等等相关内容资料加以利用解决问题。 ```c #include <stdio.h> #include <math.h> int main(void){ double result; // Example of checking before performing sqrt operation. double input_value = -1.0f; if(input_value >= 0){ result = sqrt(input_value); printf("Square root is %lf\n",result); } else{ printf("Invalid value for square root calculation.\n"); } return 0; } ``` #### 4. 特殊注意事项 当在嵌入式开发环境下工作时还需额外留意以下几个方面: - 确认所使用的工具链是否正确启用了FPU(Floating Point Unit)相关特性; - 查看当前项目配置里关于堆栈大小分配策略方面的安排是否恰当合适; - 若有必要的话还可以尝试启用更多的调试辅助功能帮助定位故障源头所在位置。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值