带误差控制的有理幂根的有理逼近

时间:2019-04-12 17:01:23

标签: algorithm math exponent approximation rational-number

我正在寻找一种算法,该算法可以有效地计算Ignoring exception in on_message Traceback (most recent call last): File "C:\Users\Jason\AppData\Local\Programs\Python\Python35\lib\site-packages\discord\client.py", line 307, in _run_event yield from getattr(self, event)(*args, **kwargs) File "C:\Users\Jason\AppData\Local\Programs\Python\Python35\PrawnBot.py", line 66, in on_message async def _kick(ctx, member: Member): File "C:\Users\Jason\AppData\Local\Programs\Python\Python35\lib\site-packages\discord\ext\commands\core.py", line 574, in decorator self.add_command(result) File "C:\Users\Jason\AppData\Local\Programs\Python\Python35\lib\site-packages\discord\ext\commands\core.py", line 487, in add_command raise discord.ClientException('Command {0.name} is already registered.'.format(command)) discord.errors.ClientException: Command kick is already registered. ,其中b^eb是有理数,以确保近似误差不会超过给定的e(合理)。明确地,我正在寻找一个功能:

err

将保留法律rational exp(rational base, rational exp, rational err)

有理数表示为大整数对。假定所有加法,乘法等合理性保留操作都已定义。

我找到了几种方法,但是它们不允许我足够清楚地控制错误。在这个问题上,我不在乎整数溢出。实现此目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

这很复杂,因此我将概述我要采用的方法。我保证不会有任何错误,您还会有很多工作要做。

我将把您所说的变量exp(x, y, err)更改为错误x^y中的err。如果y不在0 <= y < 1范围内,则我们可以轻松地将适当的x^kk乘以一个整数来做到这一点。所以我们只需要担心分数y

如果所有分子和分母都较小,则可以通过首先取整数幂,然后使用牛顿法求根来解决此问题。但是,当您尝试估计类似(1000001/1000000)^(2000001/1000000)之类的东西时,这个幼稚的想法将痛苦地崩溃。因此,面临的挑战是如何避免这种情况发生。

我建议您考虑将x^y计算为x^y = (x0^y0) * (x0^(y-y0)) * (x/x0)^y = (x0^y0) * e^((y-y0) * log(x0)) * e^(y * log(x/x0))的问题。并且我们将选择x0y0,以便计算更容易并且误差也有限。

要限制错误,我们首先可以在b上设置一个天真的上限x0^y0-类似于“比x高的下一个整数到次高整数的幂”比y”。我们将选择x0y0,使其与xy足够接近,以使后面的术语在2下。然后,我们只需要估计三个项在err/12err/(6*b)err/(6*b)中。 (您可能希望将这些错误缩小一半,然后使最终答案成为附近的有理数。)

现在,当我们选择x0y0时,我们的目标是“用小分子/分母实现接近有理”。为此,我们开始计算continued fraction。这给出了一个有理数序列,可以迅速收敛到目标实数。如果我们很快就切断了序列,那么我们可以迅速找到一个在目标实数任意距离内的有理数,同时保持相对较小的分子和分母。

让我们从第三学期开始进行研究。

我们想要y * log(x/x0) < log(2)。但是从泰勒级数中,如果x/2 < x0 < 2x,则log(x/x0) < x/x0 - 1。因此,我们可以在连续分数中搜索适当的x0

一旦找到它,就可以对log(1+z)使用泰勒级数来计算log(x/x0)内的err/(12*y*b)。然后是e^z的泰勒级数,以计算期望误差的项。

第二项比较复杂。我们需要估计log(x0)。我们要做的是找到一个合适的整数k,使得1.1^k <= x0 < 1.1^(k+1)。然后,我们可以相当精确地估计k * log(1.1)log(x0 / 1.1^k)。找到该log的幼稚上限,并使用它找到足够接近的y0以使第二项位于2之内。然后使用泰勒级数估计e^((y-y0) * log(x0))到我们想要的精度。

对于第一个术语,我们使用将x0升为整数的幼稚方法,然后使用牛顿法求根,以将x0^y0赋予我们想要的精度。

然后将它们相乘,我们得到一个答案。 (如果您选择了“更严格的错误,更好的答案”,那么现在您将对该答案做一个连续的分数以选择一个更好的返回理性。)