C++11标准模板(STL)- 常用数学函数 - 分类及比较 - 对给定的浮点值分类(std::fpclassify)

时间:2024-11-03 07:32:35

常用数学函数

对给定的浮点值分类

std::fpclassify

定义于头文件 <math.h>

#define fpclassify(arg) /* implementation defined */

(C99 起)

归类浮点值 arg 到下列类别中:零、非正规、正规、无穷大、 NaN 或实现定义类别。该宏返回整数值。

忽略 FLT_EVAL_METHOD :即使以多于参数类型的范围和精度对它求值,首先仍将它转换到其语义类型,然后分类基于该类型:正规的 long double 值可能在转换到 double 时变为非正规,而在转换到 float 时变为零。

参数

arg - 浮点值

返回值

指明 arg 类别的 FP_INFINITE 、 FP_NAN 、 FP_NORMAL 、 FP_SUBNORMAL 、 FP_ZERO 或实现定义类型之一。

#define FP_NAN		0x0100
#define FP_NORMAL	0x0400
#define FP_INFINITE	(FP_NAN | FP_NORMAL)
#define FP_ZERO		0x4000
#define FP_SUBNORMAL	(FP_NORMAL | FP_ZERO)

可能实现

namespace GGX
{
using namespace std;
constexpr int
fpclassify(float __x)
{
    return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
                                FP_SUBNORMAL, FP_ZERO, __x);
}

constexpr int
fpclassify(double __x)
{
    return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
                                FP_SUBNORMAL, FP_ZERO, __x);
}

constexpr int
fpclassify(long double __x)
{
    return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
                                FP_SUBNORMAL, FP_ZERO, __x);
}

template<typename _Tp>
constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
          int>::__type
          fpclassify(_Tp __x)
{
    return __x != 0 ? FP_NORMAL : FP_ZERO;
}
}

调用示例

#include <iostream>
#include <cstdlib>
#include <typeinfo>
#include <cinttypes>
#include <cmath>
#include <math.h>
#include <tgmath.h>
#include <stdio.h>
#include <math.h>
#include <float.h>

const char *show_classification(double x)
{
    //归类浮点值 arg 到下列类别中:零、非正规、正规、无穷大、 NaN 或实现定义类别。
    switch (std::fpclassify(x))
    {
    case FP_INFINITE:
        return "Inf";
    case FP_NAN:
        return "NaN";
    case FP_NORMAL:
        return "normal";
    case FP_SUBNORMAL:
        return "subnormal";
    case FP_ZERO:
        return "zero";
    default:
        return "unknown";
    }
}

int main(void)
{
    std::cout << "show_classification(1.0/0.0) is " << show_classification(1 / 0.0) << std::endl;
    std::cout << "show_classification(0.0/0.0) is is " << show_classification(0.0 / 0.0) << std::endl;
    std::cout << "show_classification(DBL_MIN/2) is is " << show_classification(DBL_MIN / 2) << std::endl;
    std::cout << "show_classification(-0.0 is is) " << show_classification(-0.0) << std::endl;
    std::cout << "show_classification(1.0 is is) " << show_classification(1.0) << std::endl;
    std::cout << std::endl;

    std::cout << "std::fpclassify(1.0/0.0) is " << std::fpclassify(1 / 0.0) << std::endl;
    std::cout << "std::fpclassify(0.0/0.0) is is " << std::fpclassify(0.0 / 0.0) << std::endl;
    std::cout << "std::fpclassify(DBL_MIN/2) is is " << std::fpclassify(DBL_MIN / 2) << std::endl;
    std::cout << "std::fpclassify(-0.0) is " << std::fpclassify(-0.0) << std::endl;
    std::cout << "std::fpclassify(1.0) is " << std::fpclassify(1.0) << std::endl;
    std::cout << std::endl;

    std::cout << std::hex;
    std::cout << "std::fpclassify(1.0/0.0) is " << std::fpclassify(1 / 0.0) << std::endl;
    std::cout << "std::fpclassify(0.0/0.0) is is " << std::fpclassify(0.0 / 0.0) << std::endl;
    std::cout << "std::fpclassify(DBL_MIN/2) is is " << std::fpclassify(DBL_MIN / 2) << std::endl;
    std::cout << "std::fpclassify(-0.0) is " << std::fpclassify(-0.0) << std::endl;
    std::cout << "std::fpclassify(1.0) is " << std::fpclassify(1.0) << std::endl;
    std::cout << std::endl;

    printf("show_classification(1.0/0.0) is %s\n", show_classification(1 / 0.0));
    printf("show_classification(0.0/0.0) is %s\n", show_classification(0.0 / 0.0));
    printf("show_classification(DBL_MIN/2) is %s\n", show_classification(DBL_MIN / 2));
    printf("show_classification(-0.0) is %s\n", show_classification(-0.0));
    printf("show_classification(1.0) is %s\n", show_classification(1.0));
    std::cout << std::endl;

    return 0;
}

输出

show_classification(1.0/0.0) is Inf
show_classification(0.0/0.0) is is NaN
show_classification(DBL_MIN/2) is is subnormal
show_classification(-0.0 is is) zero
show_classification(1.0 is is) normal

std::fpclassify(1.0/0.0) is 1280
std::fpclassify(0.0/0.0) is is 256
std::fpclassify(DBL_MIN/2) is is 17408
std::fpclassify(-0.0) is 16384
std::fpclassify(1.0) is 1024

std::fpclassify(1.0/0.0) is 500
std::fpclassify(0.0/0.0) is is 100
std::fpclassify(DBL_MIN/2) is is 4400
std::fpclassify(-0.0) is 4000
std::fpclassify(1.0) is 400

show_classification(1.0/0.0) is Inf
show_classification(0.0/0.0) is NaN
show_classification(DBL_MIN/2) is subnormal
show_classification(-0.0) is zero
show_classification(1.0) is normal