在STM32的MDK(Keil)环境中,判断浮点数是否为NaN有以下几种方法:
1. 使用C标准库的isnan()函数(推荐)
#include <math.h>
float f = 0.0f / 0.0f; // 产生NaN
if (isnan(f)) {
printf("f is NaN\n");
}
2. 手动实现判断逻辑
#include <stdint.h>
// 判断单精度浮点数是否为NaN
int is_float_nan(float f) {
uint32_t bits = *(uint32_t*)&f;
// IEEE 754 单精度浮点数格式:
// 符号位(1位) | 指数位(8位) | 尾数位(23位)
// NaN条件:指数全为1,尾数非0
uint32_t exponent = (bits >> 23) & 0xFF;
uint32_t mantissa = bits & 0x7FFFFF;
return (exponent == 0xFF) && (mantissa != 0);
}
// 判断双精度浮点数是否为NaN
int is_double_nan(double d) {
uint64_t bits = *(uint64_t*)&d;
// IEEE 754 双精度浮点数格式:
// 符号位(1位) | 指数位(11位) | 尾数位(52位)
uint64_t exponent = (bits >> 52) & 0x7FF;
uint64_t mantissa = bits & 0xFFFFFFFFFFFFFULL;
return (exponent == 0x7FF) && (mantissa != 0);
}
3. 利用NaN的特性:NaN != NaN
int is_nan_simple(float f) {
// 根据IEEE 754标准,NaN与自身比较不相等
return (f != f);
}
4. 完整的实用函数
#include <stdint.h>
#include <stdbool.h>
typedef union {
float f;
uint32_t u;
} FloatUnion;
bool is_nan(float value) {
FloatUnion fu = { .f = value };
// 提取指数和尾数
uint32_t exp = (fu.u >> 23) & 0xFF;
uint32_t frac = fu.u & 0x7FFFFF;
// NaN: 指数全为1(255),尾数非0
// 无穷大: 指数全为1,尾数为0
return (exp == 0xFF) && (frac != 0);
}
bool is_infinity(float value) {
FloatUnion fu = { .f = value };
uint32_t exp = (fu.u >> 23) & 0xFF;
uint32_t frac = fu.u & 0x7FFFFF;
// 无穷大: 指数全为1,尾数为0
return (exp == 0xFF) && (frac == 0);
}
5. 在MDK中的配置注意事项
# 在Keil工程中需要:
# 1. 包含math.h头文件
# 2. 可能需要启用浮点支持
# 链接数学库(如果使用isnan())
# 在Linker选项中添加:-lm
6. 示例使用
#include <stdio.h>
#include <math.h>
void check_float(float f) {
if (isnan(f)) {
printf("Value is NaN\n");
} else if (isinf(f)) {
printf("Value is Infinity\n");
} else {
printf("Value is normal: %f\n", f);
}
}
int main(void) {
float nan_val = 0.0f / 0.0f;
float inf_val = 1.0f / 0.0f;
float normal_val = 3.14159f;
check_float(nan_val); // NaN
check_float(inf_val); // Infinity
check_float(normal_val); // 正常值
return 0;
}
7. 处理特殊情况
// 同时检查NaN和无穷大
void handle_special_float(float f) {
if (isnan(f)) {
// NaN处理逻辑
printf("NaN detected\n");
} else if (!isfinite(f)) {
// 无穷大处理逻辑
printf("Infinity detected\n");
} else {
// 正常数值处理
// 可以使用fpclassify获取更详细的分类
int cls = fpclassify(f);
switch(cls) {
case FP_NORMAL: // 正规数
case FP_SUBNORMAL: // 非正规数
case FP_ZERO: // 零
// 处理逻辑
break;
}
}
}
建议
-
推荐使用
isnan()函数,它是C标准库的一部分,可移植性好 -
如果担心性能,可以使用
(f != f)的方法 -
在嵌入式系统中,注意浮点运算可能较慢,尽量减少NaN检查的频率
-
在STM32上,如果启用了FPU,这些操作会更快
测试时间 2026年1月8日
实际使用示例如下

nan GLB_QiT_KuaD[1] = nan
GLB_QiT_KuaD[1] = 2.000000

特此记录
anlog
2026年1月8日
1548

被折叠的 条评论
为什么被折叠?



