常用数学函数
计算e的给定幂减一 (ex-1)
std::expm1,
std::expm1f,
std::expm1l
float expm1f( float arg ); | (1) | (C99 起) |
double expm1( double arg ); | (2) | (C99 起) |
long double expm1l( long double arg ); | (3) | (C99 起) |
定义于头文件 | ||
#define expm1( arg ) | (4) | (C99 起) |
1-3) 计算 e (欧拉数, 2.7182818
)的给定 arg
次幂减 1.0 。若 arg
接近零,则此函数比表达式 exp(arg)-1.0 更精确。
4) 泛型宏:若 arg
拥有 long double 类型,则调用 expm1l
。否则,若 arg
拥有整数类型或 double 类型,则调用 expm1
。否则调用 expm1f
。
参数
arg | - | 浮点值 |
返回值
若不出现错误则返回 earg
-1 。
若出现上溢所致的值域错误,则返回 +HUGE_VAL
、 +HUGE_VALF
或 +HUGE_VALL
。
若出现下溢所致的值域错误,则返回(舍入后的)正确结果。
错误处理
报告 math_errhandling 中指定的错误。
若实现支持 IEEE 浮点算术( IEC 60559 ),则
- 若参数为 ±0 ,则返回不修改的参数
- 若参数为 -∞ ,则返回 -1
- 若参数为 +∞ ,则返回 +∞
- 若参数为 NaN ,则返回 NaN
注意
函数 expm1
和 log1p 对于金融计算有用:例如在计算小的日利率时: (1+x)n
-1 能表示为 expm1(n * log1p(x)) 。这些函数亦简化书写精确的反双曲函数。
对于 IEEE 兼容的 double 类型,若 709.8 < arg 则保证上溢。
调用示例
#include <iostream>
#include <cstdlib>
#include <typeinfo>
#include <cinttypes>
#include <cmath>
int main()
{
//计算浮点值 arg 的绝对值。
const float fNumber = 0.1314;
std::cout << "typeid(float).name(): " << typeid(float).name() << std::endl;
for (int i = 0; i < 18; i += 3)
{
std::cout << "std::expm1f(" << fNumber + i << "): "
<< std::expm1f(fNumber + i) << std::endl;
}
std::cout << std::endl;
for (int i = 0; i < 18; i += 3)
{
std::cout << "std::expm1f(" << -fNumber - i << "): "
<< std::expm1f(-fNumber - i) << std::endl;
}
std::cout << std::endl;
const double dNumber = 0.00001314;
std::cout << "typeid(double).name(): " << typeid(double).name() << std::endl;
for (int i = 0; i < 18; i += 3)
{
std::cout << "std::expm1(" << dNumber + i << "): "
<< std::expm1(dNumber + i) << std::endl;
}
std::cout << std::endl;
for (int i = 0; i < 18; i += 3)
{
std::cout << "std::expm1(" << -dNumber - i << "): "
<< std::expm1(-dNumber - i) << std::endl;
}
std::cout << std::endl;
const long double ldNumber = 0.00001314;
std::cout << "typeid(long double).name(): " << typeid(long double).name() << std::endl;
for (int i = 0; i < 18; i += 3)
{
std::cout << "std::expm1l(" << ldNumber + i << "): "
<< std::expm1l(ldNumber + i) << std::endl;
}
std::cout << std::endl;
for (int i = 0; i < 18; i += 3)
{
std::cout << "std::expm1l(" << -ldNumber - i << "): "
<< std::expm1l(-ldNumber - i) << std::endl;
}
std::cout << std::endl;
return 0;
}
输出
typeid(float).name(): f
std::expm1f(0.1314): 0.140424
std::expm1f(3.1314): 21.906
std::expm1f(6.1314): 459.08
std::expm1f(9.1314): 9239.95
std::expm1f(12.1314): 185608
std::expm1f(15.1314): 3.72806e+006
std::expm1f(-0.1314): -0.123133
std::expm1f(-3.1314): -0.956343
std::expm1f(-6.1314): -0.997826
std::expm1f(-9.1314): -0.999892
std::expm1f(-12.1314): -0.999995
std::expm1f(-15.1314): -1
typeid(double).name(): d
std::expm1(1.314e-005): 1.31401e-005
std::expm1(3.00001): 19.0858
std::expm1(6.00001): 402.434
std::expm1(9.00001): 8102.19
std::expm1(12): 162756
std::expm1(15): 3.26906e+006
std::expm1(-1.314e-005): -1.31399e-005
std::expm1(-3.00001): -0.950214
std::expm1(-6.00001): -0.997521
std::expm1(-9.00001): -0.999877
std::expm1(-12): -0.999994
std::expm1(-15): -1
typeid(long double).name(): e
std::expm1l(1.314e-005): 1.31401e-005
std::expm1l(3.00001): 19.0858
std::expm1l(6.00001): 402.434
std::expm1l(9.00001): 8102.19
std::expm1l(12): 162756
std::expm1l(15): 3.26906e+006
std::expm1l(-1.314e-005): -1.31399e-005
std::expm1l(-3.00001): -0.950214
std::expm1l(-6.00001): -0.997521
std::expm1l(-9.00001): -0.999877
std::expm1l(-12): -0.999994
std::expm1l(-15): -1