【问题标题】:MATLAB: very small number divided by very small numberMATLAB:非常小的数字除以非常小的数字
【发布时间】:2016-07-31 21:11:03
【问题描述】:

我有一个非常小的数字除以非常小的数字,MATLAB 给我 Inf(当 x 太小)或 NaN(当 x 为零时)。但正确的极限值应该是2。如何解决这个问题?如果xx = 0 太小,将j 设为2?

x = 0.000001

>> x = 0.000001
x =
   1.0000e-06
>> j = 2*x*(1+(-1)*exp(-x))^(-1)*exp(-x)
j =
    2.0000

x = 0.01

>> x = 0.01
x =
    0.0100
>> j = 2*x*(1+(-1)*exp(-x))^(-1)*exp(-x)
j =
    1.9900

x = 1e-19

>> x = 1e-19
x =
   1.0000e-19
>> j = 2*x*(1+(-1)*exp(-x))^(-1)*exp(-x)
j =
   Inf

x = 0

>> x = 0
x =
     0
>> j = 2*x*(1+(-1)*exp(-x))^(-1)*exp(-x)
j =
   NaN

【问题讨论】:

  • 你能清理一下公式吗?我不明白你要计算什么。我只看到 (-1).*x 是 -x 和 exp(1)^something 这只是 exp(something)。请不要让它过于复杂
  • @Andreas H. 我做到了。你能帮帮我吗?
  • Inf 边界的快速解决方法。使用min函数:f = @(x) min( 2 , 2*x*exp(-x)/(1-exp(-x)) );

标签: matlab


【解决方案1】:

x=0 得到 NaN 的事实是正确的,因为你不能除以零。限制只在x->0有效,x=0无效。

它确实适用于最多 x ~= 10^-12,问题是当指数接近 1 时,由于浮点运算的细节,您很快就会开始失去精度:

f = @(x) 2*x*exp(-x)/(1-exp(-x));
pow = (-1)*(1:19);
X = 10.^pow; % 10^-1 to 10^-19
[pow', arrayfun(f, X)']

ans =
   -1.0000    1.9017
   -2.0000    1.9900
   -3.0000    1.9990
   -4.0000    1.9999
   -5.0000    2.0000
   -6.0000    2.0000
   -7.0000    2.0000
   -8.0000    2.0000
   -9.0000    2.0000
  -10.0000    2.0000
  -11.0000    2.0000
  -12.0000    2.0000
  -13.0000    1.9994
  -14.0000    2.0016
  -15.0000    2.0016
  -16.0000    1.8014
  -17.0000       Inf
  -18.0000       Inf
  -19.0000       Inf

解决这个问题的一种方法是使用符号数学,正如另一个答案中所建议的那样。如果您想以数字方式执行此操作,则必须在距离尚未达到极限的极限点太远的点进行评估与在数值误差压倒结果的极限点太接近的点进行评估之间进行权衡。

在 FEX 上有一个很棒的 Adaptive numerical limit (and residue) estimation 提交试图实现这一点。 approach it takes 有点类似于 Richardson extrapolation 方法。特别是:

  1. 在接近限制点的几何间隔点序列处评估限制。
  2. 多项式用于拟合结果值序列。诀窍是找到第 1 步中选择的点的平衡点。它们越接近限制点,多项式拟合的扭曲程度就越大。
  3. 以多项式模型的常数项为极限。

在您的特定情况下,实用程序就像一个魅力,无需调整点的顺序。请注意,它希望您的函数被向量化,即能够在输入点向量处评估结果,因此在定义它时使用逐元素运算符:

>> f = @(x) 2.*x.*exp(-x)./(1-exp(-x));
[lim, err] = limest(f, 0) 

lim =
    2.0000
err =
   5.5161e-12

【讨论】:

  • 如何解决 Inf 和 NaN 的这个问题?
  • 同样,NaNx=0 不是问题,这是唯一合理的结果。扩展了我关于如何以数字方式处理接近极限点的x 的答案。
【解决方案2】:

你可以使用符号数学工具箱:

syms x;
limit(2*x*(1+(-1)*exp(-x))^(-1)*exp(-x), 0)

【讨论】:

  • 还有其他方法吗?符号数学工具箱使我的代码变慢。
  • 了解How to Answer。您需要提供解释。
  • @kww 抱歉回复晚了。这就是我想到的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多