【问题标题】:Division by zero when using Ln or Exp function使用 Ln 或 Exp 函数时除以零
【发布时间】:2015-04-13 19:19:35
【问题描述】:

在我的代码中,我有时会被零除。调试器始终指向包含 Ln 或 Exp 函数的行。

使用 Ln 函数。如您所见,本节中根本没有划分。 vsn 代表非常小的数字,等于 1.0e-100。

 if a3 [row] <= 0 then a := vsn else
 if a3 [row] >= 1 then a := 1 - vsn
                  else a := a3 [row];
 costTerm := costTerm -1 * y [row] * Ln (a) -
                  (1 - 1 * y [row]) * Ln (1 - a);

使用 Exp 函数:这里存在除法,但看不到它如何生成除以零错误。

function TBack_Prop.g (value: double): double;
begin
   Result := 1 / (1 + exp (-value));
end; // g //

知道我做错了什么吗?

【问题讨论】:

  • 请提供 MCVE。在您这样做之前,没有问题需要回答。
  • 有没有可能这是一个错误归因的错误,真正的问题是对Ln的负输入?
  • 谷歌搜索 LNXP1。有实现 ln(x+1) 的 Delphi 数学库,可以为小值提供更准确的结果。
  • 我想你更大的问题是你的表达式根本无法有效地评估接近 0 和 1。你真正的前进道路将涉及数学而不是编程。
  • @David,我猜你在数学上是对的。我会进去的。

标签: delphi math delphi-xe5


【解决方案1】:

ln(0) 将除以零。在您的代码中,您将 0 传递给 ln 函数。

var
  I: Double;
  vsn: Double;
begin
  I := 1.0;
  vsn := 1.0e-100;
  I := I - vsn;
  ln(1 - I);
end;

然后I := I - vsn 行并没有真正做任何事情。双精度数只有 15-16 位有效数字,因此 vsn 的值不会修改 I。然后您有 ln(1-1) 正在计算 ln(0)

exp(x) 不能小于 0。所以我无法解释在 TBack_Prop.g 中除以 0。我会说异常发生在其他地方。

【讨论】:

  • ln 域错误不是无效的浮点运算而不是零除吗?
  • ln(0) 是零除,ln 为负数是无效的浮点数。
  • @Sebastian,知道如何尽可能少地更改数字吗?我的算法有时可能会产生 0 或 1。你确定这纯粹是一个小数问题吗?尾数也被减去,如果加倍,它们可能小到大约 e-308。
  • 尽可能少地更改数字不会帮助您解决问题。
  • 您可以在应用程序启动时调用Set8087CW($133f);。然后你会得到 -INF 作为 ln(0) 的结果,而不是除以零异常(其他一些 fp 异常也会被屏蔽)。这通常用于多媒体应用程序。但要小心......这不是您需要捕获浮点异常的应用程序的解决方案。
【解决方案2】:

没有代表发表评论,我必须通过答案发表评论。

当使用实数或双精度时,vsn 的最小可用大小为 1.0e-16。这会处理@Sebastion 回答的第一个问题。

第二个问题是

(1 + exp(-value))

给出的结果为 0,因此除以零。不可能发生。
但是,一个错字

(1 - exp(-value)) or (1 - exp(value))

当然可能是罪魁祸首,但这只是在抓住稻草。

【讨论】:

  • 我在这种情况下进行了复制/粘贴,并再次检查了所有确定性。没有错字(唉 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多