NAN、QNAN、 SNAN、 IND、 INF

本文详细介绍了32位浮点数在计算机中的表示方式及其异常值的种类,包括零值、非规格化值、无穷值、NAN等,并提供了C语言中判断NAN的函数及Lua语言下的判断方法。

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

32位浮点数在机器中的表示按照IEEE的标准是这样的:
   +------+----------------+-------------------------------+   
   | 1bit |   8bit         |         23bit                 |   
   +------+----------------+-------------------------------+


其中:1bit表示符号位(0表示正,1表示负),8bit表示指数(0~255,实际指数取值还要减去127,即指数取值区间为-127~128),23bit表示尾数。

这里所要说的浮点异常值就是这种表示产生的几种特殊值,IEEE规定根据指数和尾数的不同分别可表示如下几种特殊值:


1. 零值:按上述的浮点表述形式如果指数部分全部为0,并且尾数全部为0,则表示为浮点0.0,并且规定-0 = +0

2. 非规格化值:如果指数全部为0,尾数非0,则表示非规格化的值,16进制看到的就是[80xxxxxx]h或者[00xxxxxx]h

3. 无穷值:如果指数全部为1,尾数全部为0,则根据符号位分别表示正无穷大和负无穷大,16进制看到的就是[FF800000]h或者[7F800000]h

4. NAN:如果指数全部为1,尾数非0,则表示这个值不是一个真正的值(Not A Number)。NAN又分成两类:QNAN(Quiet NAN)和SNAN(Singaling NAN)。QNAN与SNAN的不同之处在于,QNAN的尾数部分最高位定义为1,SNAN最高位定义为0;QNAN一般表示未定义的算术运算结果,最常见的莫过于除0运算;SNAN一般被用于标记未初始化的值,以此来捕获异常。


会返回 NaN 的运算有如下三种:
1. 操作数中至少有一个是 NaN 的运算
2. 未定义操作
    下列除法运算:0/0、∞/∞、∞/−∞、−∞/∞、−∞/−∞
    下列乘法运算:0×∞、0×-∞
    下列加法运算:∞ + (−∞)、(−∞) + ∞
    下列减法运算:∞ - (−∞)、(−∞) - ∞
3. 产生复数结果的实数运算。例如:
    对负数进行开方运算
    对负数进行对数运算
    对比-1小或比+1大的数进行反正弦或反余弦运算
那么既然NAN不是一个真实的数值,在程序如何判断变量是否变成了NAN呢?大部分语言中针对NAN值都有一系列的函数定义,C语言中最常见的三个函数:

_isnan(double x);                  //判断是否为NAN
_finite(double x);                  //判读是否为无穷大
_fpclass(double x);                //返回一系列的定义值,如:_FPCLASS_QNAN, _FPCLASS_SNAN
5. INF / inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。例如,当用 0 除一个整数时便会得到一个1.#INF / inf值;相应的,如果用 0 除一个负整数也会得到 -1.#INF / -inf值。

6. IND / nan:这个的情况更复杂,一般来说,它们来自于任何未定义结果(非法)的浮点数运算。"IND"是 indeterminate 的缩写,而"nan"是 not a number 的缩写。产生这个值的常见例子有:对负数开平方,对负数取对数,0.0/0.0,0.0*∞, ∞/∞ 等。


这里有个lua下的判断NAN的方法,参考http://snippets.luacode.org/snippets/Test_for_NaN_75


function isnan(x) return x ~= x end
Tests/Usage

if _TEST then -- test suite
assert(isnan(0/0))
assert(not (isnan(math.huge) or isnan(-math.huge)))
assert(not (isnan(nil) or isnan(false) or isnan(0)))
local t = setmetatable({}, {__eq = function() return false end})
assert(not isnan(t))
print 'OK'
end


原文链接:https://blog.csdn.net/lisai17/article/details/14649419

### 关于 SNaNQNaN 的定义 在浮点数标准 IEEE 754 中,存在两种类型的 NaN(Not a Number),分别是静默非数(QNaN, Quiet NaN)和信号非数(SNaN, Signal NaN)。其中,SNaN 是一种特殊形式的 NaN,在某些计算环境中会触发异常或中断程序执行[^1]。 ### 判断 SNaN 的方法 为了检测某个数值是否为 SNaN,可以利用特定的语言特性或库函数来实现。以下是几种常见编程语言中的解决方案: #### Python 实现 Python 并未直接提供内置支持用于区分 QNaNSNaN,但可以通过 NumPy 库间接完成这一操作。NumPy 提供了 `numpy.isnan` 函数以及底层位模式访问能力,允许开发者手动解析浮点数表示并识别 SNaN。 ```python import numpy as np def is_snan(value): bits = np.array([value], dtype=np.float64).view(np.uint64)[0] exponent_mask = (1 << 11) - 1 mantissa_mask = ~((1 << 52) - 1) # Check for NaN and signal bit set if ((bits >> 52) & exponent_mask) == exponent_mask and (bits & mantissa_mask) != 0: return True return False # 测试示例 print(is_snan(float('nan'))) # 输出应为False ``` 上述代码通过检查浮点数内部结构中的指数部分与尾数部分,确认其是否满足 SNaN 定义条件。 #### C/C++ 实现 C/C++ 可以更方便地操作硬件级浮点数属性,因此适合用来精确判断 SNaN 类型。 ```c++ #include <cmath> #include <cstdint> bool is_snan(double value) { uint64_t bits; std::memcpy(&bits, &value, sizeof(bits)); const uint64_t EXP_MASK = 0x7FFULL << 52; // Exponent mask const uint64_t MAN_MASK = ~(0xFFFFFFFFFFFFFULL); // Mantissa mask bool exp_all_ones = (bits & EXP_MASK) == EXP_MASK; bool man_not_zero = (bits & MAN_MASK) != 0; return exp_all_ones && man_not_zero; } // 使用方式同上 ``` 这段代码同样依赖于解码双精度浮点数二进制格式,并依据 IEEE 754 标准判定目标值是否属于 SNaN 范畴。 ### 处理子进程输出时注意事项 当涉及多线程或多进程环境下的错误捕捉机制设计时,需特别留意避免因管道缓冲区满而引发死锁现象发生。推荐采用如下策略规避风险:不单独设置 `stdout=PIPE` 或者 `stderr=PIPE` 参数;转而调用 Popen 对象所提供的 communicate 方法同步读取数据流内容[^2]。 例如: ```python from subprocess import Popen, PIPE process = Popen(['command'], stdout=PIPE, stderr=PIPE) output, error = process.communicate() if process.returncode != 0: raise Exception(f"Command failed with {error.decode()}") ``` 以上片段展示了如何安全获取外部命令的标准输出及错误消息而不至于陷入阻塞状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值