mon*_*ing 37 c c++ math function
我一直在使用isinf,isnan在Linux平台上运行完美的功能.但是这在OS-X上不起作用,所以我决定使用std::isinf std::isnan哪种适用于Linux和OS-X.
但英特尔编译器无法识别它,我猜它是英特尔编译器中的一个错误,根据http://software.intel.com/en-us/forums/showthread.php?t=64188
所以,现在我只是想避免麻烦和定义自己的isinf,isnan执行.
有谁知道如何做到这一点?
编辑:
我最终在我的源代码中进行了制作isinf/ isnan工作
#include <iostream>
#include <cmath>
#ifdef __INTEL_COMPILER
#include <mathimf.h>
#endif
int isnan_local(double x) {
#ifdef __INTEL_COMPILER
return isnan(x);
#else
return std::isnan(x);
#endif
}
int isinf_local(double x) {
#ifdef __INTEL_COMPILER
return isinf(x);
#else
return std::isinf(x);
#endif
}
int myChk(double a){
std::cerr<<"val is: "<<a <<"\t";
if(isnan_local(a))
std::cerr<<"program says isnan";
if(isinf_local(a))
std::cerr<<"program says isinf";
std::cerr<<"\n";
return 0;
}
int main(){
double a = 0;
myChk(a);
myChk(log(a));
myChk(-log(a));
myChk(0/log(a));
myChk(log(a)/log(a));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
mat*_*ath 25
您还可以使用boost来执行此任务:
#include <boost/math/special_functions/fpclassify.hpp> // isnan
if( boost::math::isnan( ... ) .... )
Run Code Online (Sandbox Code Playgroud)
Joh*_*man 21
我没试过,但我想
int isnan(double x) { return x != x; }
int isinf(double x) { return !isnan(x) && isnan(x - x); }
Run Code Online (Sandbox Code Playgroud)
会工作.感觉isinf应该有更好的方法,但这应该有效.
Amr*_*mro 16
根据此,无穷远很容易检查:
NaN有点复杂,因为它没有唯一的表示:
下面是双精度浮点情况的代码.单精度可以类似地写入(回想一下,指数是双位的11位和单位的8位):
int isinf(double x)
{
union { uint64 u; double f; } ieee754;
ieee754.f = x;
return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) == 0x7ff00000 &&
( (unsigned)ieee754.u == 0 );
}
int isnan(double x)
{
union { uint64 u; double f; } ieee754;
ieee754.f = x;
return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) +
( (unsigned)ieee754.u != 0 ) > 0x7ff00000;
}
Run Code Online (Sandbox Code Playgroud)
实现非常简单(我从OpenCV头文件中获取了这些).它使用一个大小相等的无符号64位整数的并集,您可能需要正确声明:
#if defined _MSC_VER
typedef unsigned __int64 uint64;
#else
typedef uint64_t uint64;
#endif
Run Code Online (Sandbox Code Playgroud)
这适用于Visual Studio 2008:
#include <math.h>
#define isnan(x) _isnan(x)
#define isinf(x) (!_finite(x))
#define fpu_error(x) (isinf(x) || isnan(x))
Run Code Online (Sandbox Code Playgroud)
为安全起见,我建议使用fpu_error().我相信一些数字是用isnan()获得的,有些是用isinf(),你需要两者都是安全的.
这是一些测试代码:
double zero=0;
double infinite=1/zero;
double proper_number=4;
printf("isinf(infinite)=%d.\n",isinf(infinite));
printf("isinf(proper_number)=%d.\n",isinf(proper_number));
printf("isnan(infinite)=%d.\n",isnan(infinite));
printf("isnan(proper_number)=%d.\n",isnan(proper_number));
double num=-4;
double neg_square_root=sqrt(num);
printf("isinf(neg_square_root)=%d.\n",isinf(neg_square_root));
printf("isinf(proper_number)=%d.\n",isinf(proper_number));
printf("isnan(neg_square_root)=%d.\n",isnan(neg_square_root));
printf("isnan(proper_number)=%d.\n",isnan(proper_number));
Run Code Online (Sandbox Code Playgroud)
这是输出:
isinf(infinite)=1.
isinf(proper_number)=0.
isnan(infinite)=0.
isnan(proper_number)=0.
isinf(neg_square_root)=1.
isinf(proper_number)=0.
isnan(neg_square_root)=1.
isnan(proper_number)=0.
Run Code Online (Sandbox Code Playgroud)
isnan 现在是C++ 11的一部分,包括在我认为的GCC++和Apple LLVM中.
适当的#defines和#includes应该做出合适的解决方法.
但是,我建议防止纳米发生,而不是纳米检测.
好吧,理想情况下,你要等到英特尔修复错误或提供解决方法:-)
但是,如果要检测NaN,并Inf从IEEE754值,其映射到一个整数(32位或64位取决于它是否是单或双精度),并检查指数位都是1.这表明这两个案件.
您可以通过检查尾数的高位来区分NaN和Inf.如果是1,那就NaN不是了Inf.
+/-Inf 由符号位决定.
对于单精度(32位值),符号是高位(b31),指数是接下来的8位(加上23位尾数).对于双精度,符号仍然是高位,但指数是11位(尾数加52位).
维基百科拥有所有血腥的细节.
以下代码显示了编码的工作原理.
#include <stdio.h>
static void decode (char *s, double x) {
long y = *(((long*)(&x))+1);
printf("%08x ",y);
if ((y & 0x7ff80000L) == 0x7ff80000L) {
printf ("NaN (%s)\n", s);
return;
}
if ((y & 0xfff10000L) == 0x7ff00000L) {
printf ("+Inf (%s)\n", s);
return;
}
if ((y & 0xfff10000L) == 0xfff00000L) {
printf ("-Inf (%s)\n", s);
return;
}
printf ("%e (%s)\n", x, s);
}
int main (int argc, char *argv[]) {
double dvar;
printf ("sizeof double = %d\n", sizeof(double));
printf ("sizeof long = %d\n", sizeof(long));
dvar = 1.79e308; dvar = dvar * 10000;
decode ("too big", dvar);
dvar = -1.79e308; dvar = dvar * 10000;
decode ("too big and negative", dvar);
dvar = -1.0; dvar = sqrt(dvar);
decode ("imaginary", dvar);
dvar = -1.79e308;
decode ("normal", dvar);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它输出:
sizeof double = 8
sizeof long = 4
7ff00000 +Inf (too big)
fff00000 -Inf (too big and negative)
fff80000 NaN (imaginary)
ffefdcf1 -1.790000e+308 (normal)
Run Code Online (Sandbox Code Playgroud)
请记住,这段代码(但不是方法)在很大程度上取决于你的长片的大小,而不是过于便携.但是,如果您不得不小心翼翼地获取信息,那么您已进入该领域:-)
顺便说一句,我总是发现Harald Schmidt的IEEE754转换器对浮点分析非常有用.
| 归档时间: |
|
| 查看次数: |
38522 次 |
| 最近记录: |