isnan函数、isinf函数c语言实现

isnan函数c语言实现

在C语言中,isnan 函数是 <math.h> 的一部分,用于检查一个浮点数是否是NaN(Not a Number)。然而,如果你想要了解或实现一个类似 isnan 的函数而不使用 <math.h>,你需要直接操作浮点数的位表示。这通常涉及到将浮点数视为一个整数(或一系列整数,对于双精度浮点数),并检查特定的位模式。

在IEEE 754标准中,NaN的位模式具有特定的特征:指数字段(exponent field)全为1,而尾数字段(mantissa or fraction field)不为全0。但是,需要注意的是,存在多种NaN表示,包括静默NaN(quiet NaN)和信号NaN(signaling NaN),它们在尾数字段中有所不同。

以下是一个简单的、针对IEEE 754单精度浮点数(float)的 isnan 函数的实现示例。请注意,这个实现是特定于平台的,因为它依赖于浮点数的内存布局:

#include <stdint.h>  
#include <stdbool.h>  
  
// 检查一个float是否为NaN  
bool my_isnan(float f) {  
    // 将float转换为uint32_t以便按位检查  
    uint32_t i = *(uint32_t*)&f;  
  
    // IEEE 754单精度NaN的位模式特征  
    // 指数位全为1(0x7F800000),尾数位不全为0  
    const uint32_t nan_mask = 0x7F800000;  
    const uint32_t quiet_nan_mask = nan_mask | 0x00400000; // 假设我们只关心静默NaN  
  
    // 检查是否为NaN  
    if ((i & nan_mask) == nan_mask && (i & ~quiet_nan_mask) != 0) {  
        // 这里我们只检查了是否为NaN,没有区分静默NaN和信号NaN  
        // 如果你只关心静默NaN,可以去掉 & ~quiet_nan_mask 的检查  
        return true;  
    }  
  
    // 如果不是NaN,返回false  
    return false;  
}  
  
// 注意:上面的实现对于信号NaN和某些特殊的NaN值(如伪无穷大)可能不会返回true  
// 因为我们使用了quiet_nan_mask来过滤掉一些情况。如果你想要一个更宽泛的NaN检查,  
// 可以只使用nan_mask进行比较。  
  
// 测试代码  
#include <stdio.h>  
  
int main() {  
    float testValues[] = {3.14, -0.001, 0.0, -42.0, 0.0/0.0, sqrt(-1.0)}; // 注意:sqrt(-1.0)在C中通常不产生NaN  
  
    // 为了测试NaN,我们可以使用0.0/0.0来生成一个  
    float nanValue = 0.0/0.0;  
  
    printf("Testing %f: %s\n", nanValue, my_isnan(nanValue) ? "NaN" : "Not NaN");  
  
    // 注意:sqrt(-1.0)在标准C中会产生域错误,并不直接返回NaN  
    // 如果你想要测试sqrt产生的NaN,你需要在一个支持复数或特定环境的上下文中进行  
  
    return 0;  
}

请注意,上面的 my_isnan 函数实现中,我使用了 quiet_nan_mask 来尝试过滤掉一些非NaN的值,但这可能不是必要的,具体取决于你想要如何定义“NaN”。如果你只想要检查任何形式的NaN(包括信号NaN和静默NaN),你应该只使用 nan_mask 进行比较。

另外,请注意 sqrt(-1.0) 在标准C中并不直接产生NaN;它会导致运行时错误(除非你在一个支持复数运算的环境中)。为了测试NaN,我使用了 0.0/0.0 来生成一个。

isinf c语言实现

在C语言中,isinf 函数是标准库 <math.h> 的一部分,用于检查一个浮点数是否是无穷大(不管是正无穷大还是负无穷大)。然而,如果你想要了解或实现一个类似 isinf 的函数而不直接使用 <math.h> 中的实现,你需要直接操作浮点数的位表示。

以下是一个基于IEEE 754标准实现的 isinf 函数的简单示例,该示例适用于单精度浮点数(float)和双精度浮点数(double)。请注意,这个实现是特定于符合IEEE 754标准的平台的。

单精度浮点数(float)

#include <stdint.h>  
#include <stdbool.h>  
  
bool isinf_float(float f) {  
    // 将float转换为uint32_t以便按位检查  
    uint32_t i = *(uint32_t*)&f;  
  
    // IEEE 754单精度无穷大的位模式特征  
    // 指数位全为1(0x7F800000),尾数位全为0  
    const uint32_t inf_mask = 0x7F800000;  
    const uint32_t nan_or_inf_mask = inf_mask | 0x007FFFFF; // 用来检查是否是NaN或Inf  
  
    // 检查是否为无穷大  
    // 首先排除NaN(因为NaN的指数位也全为1,但尾数位不全为0)  
    // 然后检查是否为无穷大  
    return (i & nan_or_inf_mask) == inf_mask;  
}

双精度浮点数(double)

对于双精度浮点数,你需要使用64位整数(uint64_t)来检查:

#include <stdint.h>  
#include <stdbool.h>  
  
bool isinf_double(double d) {  
    // 将double转换为uint64_t以便按位检查  
    uint64_t i = *(uint64_t*)&d;  
  
    // IEEE 754双精度无穷大的位模式特征  
    // 指数位全为1(0x7FF0000000000000),尾数位全为0  
    const uint64_t inf_mask = 0x7FF0000000000000ULL;  
    const uint64_t nan_or_inf_mask = inf_mask | 0x000FFFFFFFFFFFFFULL; // 用来检查是否是NaN或Inf  
  
    // 检查是否为无穷大  
    // 排除NaN,然后检查是否为无穷大  
    return (i & nan_or_inf_mask) == inf_mask;  
}

 

请注意,在上述代码中,我使用了 ULL 后缀来确保 inf_mask 和 nan_or_inf_mask 常量被正确地视为无符号的64位整数。

这些函数将返回 true 如果传入的浮点数是一个无穷大值(不管是正的还是负的),否则返回 false。由于IEEE 754标准中正负无穷大的表示仅在符号位上有所不同,而这些函数并不检查符号位,因此它们不会区分正无穷大和负无穷大。如果你需要区分它们,你可以使用 signbit 函数(也在 <math.h> 中)来检查浮点数的符号。

signbit c语言实现

在C语言中,signbit 函数是标准库 <math.h> 的一部分,用于检查浮点数的符号位。然而,如果你想要自己实现一个类似 signbit 的函数而不直接使用 <math.h> 中的实现,你可以通过直接操作浮点数的位表示来检查符号位。

以下是一个基于IEEE 754标准实现的 signbit 函数的简单示例,该示例同时适用于单精度浮点数(float)和双精度浮点数(double)。请注意,这个实现是特定于符合IEEE 754标准的平台的。

单精度浮点数(float)

#include <stdint.h>  
#include <stdbool.h>  
  
bool signbit_float(float f) {  
    // 将float转换为uint32_t以便按位检查  
    uint32_t i = *(uint32_t*)&f;  
  
    // IEEE 754单精度浮点数的符号位位于最高位(第31位)  
    const uint32_t sign_mask = 0x80000000;  
  
    // 检查符号位  
    return (i & sign_mask) != 0;  
}

双精度浮点数(double)

#include <stdint.h>  
#include <stdbool.h>  
  
bool signbit_double(double d) {  
    // 将double转换为uint64_t以便按位检查  
    uint64_t i = *(uint64_t*)&d;  
  
    // IEEE 754双精度浮点数的符号位位于最高位(第63位)  
    const uint64_t sign_mask = 0x8000000000000000ULL;  
  
    // 检查符号位  
    return (i & sign_mask) != 0;  
}

 

在这两个示例中,我们首先将浮点数(float 或 double)的地址转换为指向无符号整数(uint32_t 或 uint64_t)的指针,然后通过解引用该指针来获取浮点数的位表示。然后,我们使用一个掩码(sign_mask)来提取符号位,并检查它是否为1(表示负号)。

请注意,这些函数仅返回浮点数的符号位的状态,而不考虑该数是否为NaN、无穷大或零。如果你想要一个更全面的分类函数,你可能需要实现一个像我之前提到的 classify_float 或 classify_double 函数,该函数结合了 signbitisinf 和 isnan(或类似的位检查逻辑)的功能。然而,请注意,isnan 函数通常也需要特定的实现,因为它不能直接通过位检查来可靠地确定一个数是否为NaN(特别是当NaN的表示不遵循IEEE 754标准时)。但在IEEE 754标准下,你可以通过检查指数位全为1且尾数位不全为0来识别NaN。

特此记录

anlog

2024年9月24日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值