计算机如何计算指数函数
计算机是如何计算指数函数 e x e^{x} ex 的呢?
本文并不是为了探究各种编程语言中数学计算函数库对 e x e^x ex 函数的具体实现,而是提供一种计算思路,来帮助理解 e x e^x ex 函数的计算原理,并使用 C 语言来实现这个算法。
计算原理
泰勒展开
函数 exp ( x ) = e x \exp{(x)} = e^x exp(x)=ex 的图像如下所示:
与计算对数函数 log x \log{x} logx 相似,指数函数的计算也是对 x x x 进行处理后,使用泰勒公式进行展开计算。
指数函数 e x e^x ex 的泰勒展开如下:
e x = ∑ n = 0 n = ∞ 1 n ! x n = 1 + x + 1 2 ! x 2 + 1 3 ! x 3 + 1 4 ! x 4 + ⋅ ⋅ ⋅ + 1 n ! x n ( x → 0 , n → ∞ ) (1) e^x = \sum_{n = 0}^{n = \infty} \frac{1}{n!} x^n = 1 + x + \frac{1}{2!} x^2 + \frac{1}{3!} x^3 + \frac{1}{4!} x^4 +···+ \frac{1}{n!} x^n \quad(x \rightarrow 0, n\rightarrow \infty) \tag{1} ex=n=0∑n=∞n!1xn=1+x+2!1x2+3!1x3+4!1x4+⋅⋅⋅+n!1xn(x→0,n→∞)(1)
对 e x e^x ex 进行展开也是有条件的,那便是要求 x → 0 x \rightarrow 0 x→0 ,即以上的展开式只对 x x x 在 0 点附近有效。
同时,展开式的精度和 x x x 与 0 点的距离和展开的项数有关,如下:
以上是对 e x e^x ex 分别进行两项、四项、六项展开的图像。各自的误差如下:
可以看出,在相同的展开项数下, x x x 越靠近 0 点,误差越小; x x x 固定时,展开项数越多,误差越小。
参数归约化
为了能够更加精确计算出更大范围的 x x x 值的 e x e^x ex 结果,首先要对原式进行处理。
我们知道,在计算机中,实数使用 IEEE 浮点数来表示,那么计算机其实更加善于计算 2 x 2^x 2x,只要对浮点数的阶码进行处理就能计算得出 2 x 2^x 2x 的结果。
那么我们就要想办法,将以 e e e 为底的指数函数 e x e^x ex 转化为以 2 为底的指数函数 2 x 2^x 2x的计算,至少要部分转化。
我们知道:
e = 2 log 2 e (2) e = 2^{\log_2{e}} \tag{2} e=2log2e(2)
于是:
e x = ( 2 log 2 e ) x = 2 x log 2 e (3) e^x = (2^{\log_2{e}})^x = 2^{x\log_2{e}} \tag{3} ex=(2log2e)x=2xlog2e(3)
其中 log 2 e ≈ 1.442695 \log_2e \approx 1.442695 log2e≈1.442695 为常数,那么我们就成功地将计算 e x e^x ex 的问题转换为计算 2 x log 2 e 2^{x\log_2e} 2xlog2e 的问题了。
令 t = x log 2 e t = x\log_2{e} t=xlog2e,则:
e x = 2 x log 2 e = 2 t , ( t = x log 2 e ) (4) e^x = 2^{x\log_2{e}} = 2^{t}, \qquad (t= x^{\log_2{e}}) \tag{4} ex=2xlog2e=2t,(t=xlog2e)(4)
但是问题又来了,通过构造阶码的形式来计算 2 的次幂,只能计算 2 的整数次幂,而 t t t 为实数,那该怎么办呢?
这时要利用指数函数的一个性质:
a b + c = a b ⋅ a c (5) a^{b+c} = a^b \cdot a^c \tag{5} ab+c=ab⋅ac(5)
我们将 t t t 分为整数部分 m m m 与 小数部分 n n n,则:
令: t = [ t ] + ( t − [ t ] ) = m + n , ( m = [ t ] , n = t − [ t ] ) 则: 2 t = 2 m + n = 2 m ⋅ 2 n (6) 令:t = [t] + (t-[t]) = m + n, (m = [t], n = t-[t]) \\ 则:2^{t} = 2^{m+n} = 2^{m} \cdot 2^{n} \tag{6} 令:t=[t]+(t−[t])=m+n,(m=[t],n=t−[t])则:2t=2m+n=2m⋅2n(6)
对于整数次幂 2 m 2^m 2m 可通过构造阶码的形式来实现,对于小数次幂 2 n 2^n 2n ,则可对其进行再次转化为 e x e^x ex 的形式,对其进行展开:
因为 2 = e ln 2 2 = e^{\ln2} 2=eln2 ,所以:
2 n = ( e ln 2 ) n = e n ln 2 (7) 2^n = (e^{\ln2})^n = e^{n\ln2} \tag{7} 2n=(eln2)n=enln2(7)
因为 n ∈ ( − 1 , 1 ) , ln 2 ≈ 0.693147 n \in (-1,1),\ln2 \approx 0.693147 n∈(−1,1),ln2≈0.693147 ,所以 n ln 2 ∈ ( − 0.693147 , + 0.693147 ) n\ln2 \in (-0.693147, +0.693147) nln2∈(−0.693147,+0.693147) ,已经足够接近 0 点,所以可以对其使用泰勒展开进行计算。
令 k = n ln 2 , k ∈ ( − 0.693147 , + 0.693147 ) k = n\ln2,\quad k \in (-0.693147, +0.693147) k=nln2,k∈(−0.693147,+0.693147),则:
2 n = e k , ( k = n ln 2 ) (8) 2^n = e^k, \quad (k = n\ln2) \tag{8} 2n=ek,(k=nln2)(8)
那么:
e x = 2 x log 2 e = 2 t = 2 m + n ( t = x l o g 2 e , m = [ t ] , n = t − [ t ] ) = 2 m ⋅ 2 n = 2 m ⋅ e n ln 2 = 2 m ⋅ e k ( k = n ln 2 , n ∈ ( − ln 2 , + ln 2 ) ) \begin{align} e^x &= 2^{x\log_2{e}} \\ & = 2^t = 2^{m+n} \qquad (t = xlog_2{e}, m = [t], n = t - [t]) \\ & = 2^m \cdot 2^n \\ & = 2^m \cdot e^{n\ln2} = 2^m \cdot e^k \qquad (k = n\ln2, n \in (-\ln2, +\ln2)) \end{align} ex=2xlog2e=2t=2m+n(t=xlog2e,m=[t],n=t−[t])=2m⋅2n=2m⋅enln2=2m⋅ek(k=nln2,n∈(−ln2,+ln2))
对于 e k e^k ek,根据 (1) 式:
e k = ∑ n = 0 ∞ 1 n ! k n = 1 + k + 1 2 ! k 2 + 1 3 ! k 3 + 1 4 ! k 4 + 1 5 ! k 5 + o ( k 5 ) e^k = \sum_{n = 0}^{\infty} \frac{1}{n!} k^n = 1 + k + \frac{1}{2!}k^2 + \frac{1}{3!}k^3 + \frac{1}{4!}k^4 + \frac{1}{5!}k^5 + o(k^5) ek=n=0∑∞n!1kn=1+k+2!1k2+3!1k3+4!1k4+5!1k5+o(k5)
实现思路
先将 x x x 乘以 log 2 e ≈ 1.442695 \log_2{e} \approx 1.442695 log2e≈1.442695 得到 t t t:
float x = 3.14;
float t = x * 1.442695; // 1.442695 = log2(e)
分别取得 t t t 的整数部分 m m m 和小数部分 n n n:
m = (round)((int)(t * 2.0) / 2);
float n = t - int(t);
通过 m m m 来构造 2 m 2^m 2m:
m = (m + 127) << 23;
然后将 n n n 乘以 ln 2 \ln2 ln2 得到 k k k:
float k = n * 0.693147; // 0.693147 = ln(2)
再使用泰勒公式将其展开即可。
代码实现
源码
#include <stdio.h>
#include <math.h>float my_exp(float x){float t = x * 1.442695;int m = 0;float n = 0;m = (round)((int)(t * 2.0) / 2);n = t - m;m = (m + 127) << 23; n = n * 0.693147;float tmp_n = n;float j = 1;float result = 1 + n;for (int i = 2; i < 7; i++){j = j * i;tmp_n = tmp_n * n;result += tmp_n / j;}return *(float *)&m * result;
}int main(int argc, char *argv[]) {my_exp(3.14);for (int i = -10; i <= 30; i++){float x = i * 0.1;printf("x = %2.6f, my log(x) = %2.6f, log(x) = %2.6f, err = %2.6f\n", x, my_exp(x), exp(x), fabs(my_exp(x) - exp(x)));}return 0;
}
运行结果
计算机如何计算指数函数相关推荐
- 计算机如何计算对数函数
计算机是如何计算对数函数 log a x \log_a{x} logax 的呢? 本文并不是为了探究各种编程语言中数学计算函数库对 log \log log 函数的具体实现,而是提供一种计算 ...
- 如何利用计算机计算天数,计算机如何计算两个日期之间的天数
计算机是如何计算两个日期之间的天数的,这个问题看起来好像很简单,但是仔细一想,好像还没那么简单,月与月之间天数不一样,平年和闰年也会影响天数. 举个例子: 2017年2月1日-2017年6月1日中间有 ...
- 计算机数日期,计算机如何计算两个日期之间的天数
计算机是如何计算两个日期之间的天数的,这个问题看起来好像很简单,但是仔细一想,好像还没那么简单,月与月之间天数不一样,平年和闰年也会影响天数. 举个例子: 2017年2月1日-2017年6月1日中间有 ...
- 监控摄像头1天存储计算机,如何计算一个摄像机一天占用多少的存储量?
原标题:如何计算一个摄像机一天占用多少的存储量? 如何计算硬盘能存多长时间的监控视频,如何计算一个摄像机一天占用多少的存储量?现总结网上资料,做出以下言简意赅的总结: 1.IPC码流 摄像机的码流即监 ...
- 置信区间用计算机如何计算,正态分布置信概率和置信区间的计算机自动计算
本文提出了不确定度分析中常用的正态分布置信概率.置信区间的几种近似算法.并根据这些算法的数学模型设计了计算程序,对实际计算结果进行了验证. 维普资讯 http://doc.xuehai.net ●匝墨 ...
- 围棋的分数计算机,如何计算围棋比赛的分数【围棋知识】
原标题:如何计算围棋比赛的分数[围棋知识] ZM-GO关注 围棋比赛中分数的计算 周末围棋 围棋升段赛中会产生三个分数:大分 小分 总得分 01 大分 大分是指个人积分,嬴一盘2分,负一盘0分: 02 ...
- 华为计算机如何计算sina,一道华为的“简单四则运算”题
*expStr: 表达式字符串: [输出] 无 [返回] 计算结果 int calcucate(int len, char* expStr) { //算法思路:先乘除,后加减 assert(expSt ...
- casio计算机如何计算标准差,怎样在卡西欧5800里计算标准差和方差,不要普通计算,用里面设计好的模式,...
5800的SD模式,是"单变量统计计算模式" 按mode 3键进入,状态行显示SD,如下图 X 串列用于输入单变量观测数据,FREQ 串列用于输入观测数据的频度. 如果没有FREQ ...
- 能将无理数化为根号形式的计算机,怎么证明根号2是无理数,我们来推导和计算,还有逼格极高的算法...
原标题:怎么证明根号2是无理数,我们来推导和计算,还有逼格极高的算法 记得上学的时候忙着考试,把心头的一些为什么都压在了脑后. 面对未知,我们大多数人都选择了默认接受,其实你不懂根号2, 比如:根号2 ...
最新文章
- 如何向非技术人员解释“稀疏傅里叶变换”算法?
- 劣质代码评析——《写给大家看的C语言书(第2版)》附录B之21点程序(一)
- Hyper-V 3.0部署PART 14:准备仲裁磁盘
- 计算机考试时间改革,武汉计算机二级考试时间和改革变化2021
- navicat数据库运行存储过程
- 你还在用 Date?建议使用 LocalDateTime 了!
- JUC:ConcurrentHashMap(并发容器)
- 理论 | 三天两夜,万字长文,吃透TCP/IP
- 笔记本电脑黑屏但还在运作怎么办
- 【转】Redis学习---阿里云Redis多线程性能增强版详解
- Scala学习07——隐式转换
- oracle weblogic 补丁,Oralce weblogic 补丁下载方法
- BXP的PNP的新做法(转)
- 181225 Matlab图解峰度kurtosis与偏度skewness
- 装修行业怎么找精准客户?有那些获客渠道?
- 人月神话(四)削足适履、提纲挈领、未雨绸缪
- 如何甄选出一个优秀的软件供应商?by彭文华
- 89. 格雷编码 Python
- BI神器Power Query(3)-- PQ从表格导入数据
- 雷电网络(二):掌握雷电网络的特点 | 区块链技术博客
热门文章
- 计算机网络的形成和发展
- javascript 方法 一直提示 对象不支持此属性或方法
- Linux磁盘分区初始化
- mysql 5.6.35anzhaung_MySQL安装与配置(5.6.12,参考乐沙弥博客,未完成)
- 湖北省创新型中小企业培育申报流程方法及申报时间要求指南
- 清亡之路(4):最受误解的东南互保
- Ant Design Pro右上角个人设置管理
- 文献解读 | m6A——程序性细胞死亡与癌症的“双刃剑”
- MATLAB-数据类型之复数、字符串
- yolov4中的route和shortcut层