【问题标题】:Implement x^(e) in Extended Pascal, without using exponentiation operators在扩展 Pascal 中实现 x^(e),而不使用幂运算符
【发布时间】:2017-06-01 10:44:05
【问题描述】:

我正在构建的 Pascal ISO 10206 程序的一部分要求我实现一个函数,将实数 (x) 取幂为欧拉数 (e),而不使用 Pascal(**,pow, exp...)。

我已经尝试了几个小时的不同算法,但如果不使用已经包含的幂函数,我无法弄清楚如何做到这一点。

任何帮助将不胜感激。任何某种数学算法等...提前致谢。

【问题讨论】:

  • 这似乎是在浪费时间。不使用 exp 是没有意义的。无论如何,您可以通过一些研究找到已发布的算法。你做了什么研究?
  • 看看Taylor series。它们可用于计算值 x(以及更多)的Exp()。只需使用循环来增加、添加或乘以系列中的值。
  • FWIW,你有一个 Free Pascal 的标签,但你说你正在使用 Extended Pascal。这些不一样。您是在寻找 x^e 还是 e^x?后者是Exp()函数,但前者也可以用它来计算。
  • @RudyVelthuis 不是真的。无限和的收敛速度太慢而无用。
  • 您确定您的意思是x^e 而不是e^x?后者是一个非常更常用的功能。

标签: pascal pow exponentiation exp


【解决方案1】:

正如其他人所说,使用Exp() 或基于它的函数是没有意义的。但是,如果您真的必须使用其他东西,并且不想过于技术/数学,那么以下应该可以工作(真正的算法要复杂得多,并且需要更多的数学知识)。

该程序将泰勒级数的前 N ​​项用于 X 的小数部分,将二进制取幂用于 X 的整数部分。它可能不是很快,但相当准确,即使对于较大的指数也是如此。为了比较,我还显示Exp(X)。如果您的 Pascal 有 DoubleExtended 类型,请使用它们而不是 Real

program SimplePower;

{ Required for Delphi, you can omit it in other Pascals: }
{$APPTYPE CONSOLE}

{ Returns approximate value of e^X using sum of first N terms of Taylor series.
  Works fine with X values between 0 and 1.0 and N ~ 30. }
function Exponential(N: Integer; X: Real): Real;
var
  I: Integer;
begin
  Result := 1.0;
  for I := N - 1 downto 1 do
    Result := 1.0 + X * Result / I;
end;

{ Binary exponentiation of Base by integer Exponent. }
function IntegerExp(Base: Real; Exponent: Integer): Real;
begin
  Result := 1.0;
  while Exponent > 0 do
  begin
    if Odd(Exponent) then
      Result := Result * Base;
    Base := Base * Base;
    Exponent := Exponent shr 1;
  end;
end;

{ Combines IntegerExp function for integral part with 
  Exponential function for fractional part. }
function MyExp(N: Integer; X: Real): Real;
const
  E = 2.7182818284590452353602874713527; { from Google: "e euler" }
var
  Factor: Real;
  Fraction: Real;
begin
  Fraction := Exponential(N, Frac(X));
  Factor := IntegerExp(E, Trunc(X));
  Result := Factor * Fraction;
end;

{ Simple demo: }
const
  N = 30;
  X = 73.4567890242421234;

begin
  Writeln('MyExp(', N, ', ', X:22:18, ') = ', MyExp(N, X):22:18);
  Writeln('Exp(', X:22:18, ')       = ', Exp(X):22:18);
end.

参考:

我没有为负指数做任何事情,但只知道Exp(-x) = 1/Exp(x)。你可以用这些知识修改MyExp

【讨论】:

  • 我看到两个反对票。关于“为什么”的评论会很好。
【解决方案2】:

我使用了@RudyVelthuis 在其他帖子中指出的解决方案,但对其进行了一些修改。它基于 x^0.5 = sqrt(x),我们可以利用它来发挥我们的优势。我会留下我使用的 Pascal ISO 10206 代码。谢谢大家的帮助,特别是鲁迪。

function MyPow(base,power,precision:real):real;
begin
    if (power<0) then MyPow:=1/MyPow(base,-power,precision)
    else   if (power>=10) then MyPow:=sqr(MyPow(base,power/2,precision/2))
    else   if (power>=1) then MyPow:=base*MyPow(base,power-1,precision)
    else   if (precision>=1) then MyPow:=sqrt(base)
    else MyPow:=sqrt(MyPow(base,power*2,precision*2));
end; 

【讨论】:

  • 这很酷。但请注意,我给出的解决方案稍微准确一些。在原版中,我使用了 Delphi 的 Extended(80 位)类型,它始终给出正确的结果。
猜你喜欢
  • 1970-01-01
  • 2021-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 2020-10-22
  • 1970-01-01
  • 2011-01-11
相关资源
最近更新 更多