函数族定义---双曲函数
- cosh---计算双曲余弦函数
- sinh---计算双曲正弦函数
- tanh---计算双曲正切函数
- acosh---计算双曲余弦面积
- asinh---计算双曲正弦面积
- atanh---计算双曲正切面积 同样的,我们来分析看下sinh的计算过程 glibc/sysdeps/ieee754/dbl-64/e_sinh.c
44 double45 __ieee754_sinh (double x)
46 {
47 double t, w, h;
48 int32_t ix, jx;
49 uint32_t lx;
50
51 /* High word of |x|. */52 GET_HIGH_WORD (jx, x);
53 ix = jx & 0x7fffffff;
54
55 /* x is INF or NaN */56 if (__glibc_unlikely (ix >= 0x7ff00000))
57 return x + x;
58
59 h = 0.5;
60 if (jx < 0)
61 h = -h;
62 /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */63 if (ix < 0x40360000) /* |x|<22 */64 {
65 if (__glibc_unlikely (ix < 0x3e300000)) { /* |x|<2**-28 */66 math_check_force_underflow (x);
67 if (shuge + x > one)
68 return x;
69 /* sinh(tiny) = tiny with inexact */70 }
71 t = __expm1 (fabs (x));
72 if (ix < 0x3ff00000)
73 return h * (2.0 * t - t * t / (t + one));
74 return h * (t + t / (t + one));
75 }
76
77 /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */78 if (ix < 0x40862e42)
79 return h * __ieee754_exp (fabs (x));
80
81 /* |x| in [log(maxdouble), overflowthresold] */82 GET_LOW_WORD (lx, x);
83 if (ix < 0x408633ce || ((ix == 0x408633ce) && (lx <= (uint32_t) 0x8fb9f87d)))
84 {
85 w = __ieee754_exp (0.5 * fabs (x));
86 t = h * w;
87 return t * w;
88 }
89
90 /* |x| > overflowthresold, sinh(x) overflow */91 return math_narrow_eval(x * shuge);
92 }
通过对源码的阅读,我们也能比较清晰的了解它的计算原理:
- 获取输入double的高位字jx,并且截断符号位得到ix;
- 判断无穷大(INF)和Nan的情况,直接返回x+x;
- 对ix进行划分:
- ix < 0x40360000:|x| in [0,22],使用sign(x)0.5(E+E/(E+1)))进行计算,同时注意一些边界条件;
- ix < 0x40862e42:|x| in [22, log(maxdouble)],使用0.5*exp(|x|)进行计算;
- ix < 0x408633ce || ((ix == 0x408633ce) && (lx <= (uint32_t) 0x8fb9f87d)):|x| in [log(maxdouble), overflowthresold],使用hwwexp(0.5|x|)进行计算;
- 其它情况,出现越界了,|x| > overflowthresold, sinh(x) overflow。
函数族定义---指数和对数函数
exp---返回自然对数e的x次方
double exp (double x);
frexp---获取有效数字和指数
double frexp (double x , int* exp);
其中x为输入数,exp为存储指数的地址,计算如下的公式
$$$$x = significand*2^{exponent} $$$$其中,significand在[0.5,1) 之间
如:
param = 8.0;
result = frexp (param , &n);
printf ("%f = %f * 2^%d\n", param, result, n);
//输出结果:
//8.000000 = 0.500000 * 2^4
复制代码
ldexp---生成数字和指数有效数字
double ldexp (double x , int exp);
返回 $$$$x * 2^{exp} $$$$如:
param = 0.95;
n = 4;
result = ldexp (param , n);
printf ("%f * 2^%d = %f\n", param, n, result);
输出结果:
0.950000 * 2^4 = 15.200000
log---返回自然对数
double log (double x);
log10---返回以10为底的对数
double log10 (double x);
如:
param = 1000.0;
result = log10 (param);
printf ("log10(%f) = %f\n", param, result );
//返回结果
log10(1000.000000) = 3.000000
modf---将数字拆分为整数和分数两个部分
double modf (double x , double* intpart);
x为输入数字,intpart保存整数部分,小数部分返回,同时,整数部分和小数部分的符号相同
exp2---计算$$$$2^x $$$$
double exp2 (double x);
expm1---计算$$$$e^x-1 $$$$
double expm1 (double x);
ilogb---返回以2为底对数的整数部分
int ilogb (double x);
先对x做以2为底的对数,然后取出其中的整数部分返回 如:
param = 10.0;result = ilogb (param);
printf ("ilogb(%f) = %d\n", param, result);
//输出结果
ilogb(10.000000) = 3
因为8<10<16,所以log2(8)<log2(10)<log2(16)log_2(8)<log_2(10)<log_2(16)log2(8)<log2(10)<log2(16)即,3<log2(10)<43<log_2(10)<43<log2(10)<4,取其中的整数部分就是3。
log1p---返回ln(1+x)
double log1p (double x);
log2---返回$$$$log_2{x} $$$$
double log2 (double x);
如:
param = 1024.0;
result = log2 (param);
printf ("log2 (%f) = %f.\n", param, result );
//输出结果
log2 (1024.000000) = 10.000000
logb---返回以FLT_RADIX为底的对数,在大多数平台上,这个值为2
double logb (double x);
基本同log2
scalbn---计算$$$$x * {FLT\_RADIX}^n $$$$
double scalbn (double x , int n);
复制代码
如:
param = 1.50;
n = 4;
result = scalbn (param , n);
printf ("%f * %d^%d = %f\n", param, FLT_RADIX, n, result);
//输出结果:
1.500000 * 2^4 = 24.000000
scalbln---同scalbn,第二个入参可以是long
double scalbln (double x , long int n);
后续函数分析见下一节
标签:ix,头文件,double,param,---,源码,C++,exp,result From: https://blog.51cto.com/u_15830688/5893764