有没有更有效的对数嵌套方法? [英] Is there a more efficient way of nesting logarithms?

查看:104
本文介绍了有没有更有效的对数嵌套方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是这里发布的两个问题的延续,

This is a continuation of the two questions posted here,

在 Matlab 中声明函数递归序列

在 Pari-GP 中嵌套特定递归

长话短说,我构建了一系列函数来求解四次函数方程.我已经证明这些东西是全纯的.现在是时候制作图表了,或者至少是一些可以通过的代码来评估这些事情.我的精度已经达到了大约 13 位有效数字,但是如果我尝试获得更多,我会遇到一个特定的错误.该错误实际上只不过是溢出错误.但这是一个特殊的溢出错误;Pari-GP 似乎不喜欢嵌套对数.

To make a long story short, I've constructed a family of functions which solve the tetration functional equation. I've proven these things are holomorphic. And now it's time to make the graphs, or at least, somewhat passable code to evaluate these things. I've managed to get to about 13 significant digits in my precision, but if I try to get more, I encounter a specific error. That error is really nothing more than an overflow error. But it's a peculiar overflow error; Pari-GP doesn't seem to like nesting the logarithm.

我的特定数学函数是通过取一些大的(想想 e^e^e^e^e^e^e 的顺序)来产生小的(e^(-n) 的顺序)来近似的.数学本身需要大值的样本来产生这些小值.奇怪的是,随着我们越来越接近数值近似(大约 13 个有效数字左右),我们也越来越接近溢出,因为我们需要如此大的值来获得这 13 个有效数字.我是一个糟糕透顶的程序员;我想知道是否有一些我没有看到的解决方法.

My particular mathematical function is approximated by taking something large (think of the order e^e^e^e^e^e^e) to produce something small (of the order e^(-n)). The math inherently requires samples of large values to produce these small values. And strangely, as we get closer to numerically approximating (at about 13 significant digits or so), we also get closer to overflowing because we need such large values to get those 13 significant digits. I am a god awful programmer; and I'm wondering if there could be some work around I'm not seeing.

/*
This function constructs the approximate Abel function
The variable z is the main variable we care about; values of z where real(z)>3 almost surely produces overflow errors
The variable l is the multiplier of the approximate Abel function
The variable n is the depth of iteration required
n can be set to 100, but produces enough accuracy for about 15 
The functional equation this satisfies is exp(beta_function(z,l,n))/(1+exp(-l*z)) = beta_function(z+1,l,n); and this program approaches the solution for n to infinity
*/

beta_function(z,l,n) =
{
    my(out = 0);
    for(i=0,n-1,
        out = exp(out)/(exp(l*(n-i-z)) +1));
    out;
}

/*
This function is the error term between the approximate Abel function and the actual Abel function
The variable z is the main variable we care about
The variable l is the multiplier
The variable n is the depth of iteration inherited from beta_function
The variable k is the new depth of iteration for this function
n can be set about 100, still; but 15 or 20 is more optimal. 
Setting the variable k above 10 will usually produce overflow errors unless the complex arguments of l and z are large. 
Precision of about 10 digits is acquired at k = 5 or 6 for real z, for complex z less precision is acquired. k should be set to large values for complex z and l with large imaginary arguments.
*/

tau_K(z,l,n,k)={
    if(k == 1, 
      -log(1+exp(-l*z)), 
      log(1 + tau_K(z+1,l,n,k-1)/beta_function(z+1,l,n)) - log(1+exp(-l*z))
    )
}

/*
This is the actual Abel function
The variable z is the main variable we care about
The variable l is the multiplier
The variable n is the depth of iteration inherited from beta_function
The variable k is the depth of iteration inherited from tau_K
The functional equation this satisfies is exp(Abl_L(z,l,n,k)) = Abl_L(z+1,l,n,k); and this function approaches that solution for n,k to infinity
*/

Abl_L(z,l,n,k) ={
    beta_function(z,l,n) + tau_K(z,l,n,k);
}

这是用于逼近我已经证明是全纯的函数的代码;但遗憾的是,我的代码太可怕了.在这里,附加了一些预期的输出,您可以在其中看到满足约 10 - 13 位有效数字的函数方程.

This is the code for approximating the functions I've proven are holomorphic; but sadly, my code is just horrible. Here, is attached some expected output, where you can see the functional equation being satisfied for about 10 - 13 significant digits.

Abl_L(1,log(2),100,5)

%52 = 0.1520155156321416705967746811

exp(Abl_L(0,log(2),100,5))

%53 = 0.1520155156321485241351294757

Abl_L(1+I,0.3 + 0.3*I,100,14)

%59 = 0.3353395055605129001249035662 + 1.113155080425616717814647305*I

exp(Abl_L(0+I,0.3 + 0.3*I,100,14))

%61 = 0.3353395055605136611147422467 + 1.113155080425614418399986325*I

Abl_L(0.5+5*I, 0.2+3*I,100,60)

%68 = -0.2622549204469267170737985296 + 1.453935357725113433325798650*I

exp(Abl_L(-0.5+5*I, 0.2+3*I,100,60))

%69 = -0.2622549205108654273925182635 + 1.453935357685525635276573253*I 

现在,您会注意到我必须为不同的值更改 k 值.当参数 z,l 离实轴更远时,我们可以使 k 非常大(并且我们必须获得良好的精度),但最终它仍然会溢出;通常,一旦我们达到了大约 13-15 位有效数字,函数就会开始爆炸.您会注意到,设置 k = 60,意味着我们采用 60 对数.这听起来已经是个坏主意了,哈哈.但在数学上,值 Abl_L(z,l,infinity,infinity) 正是我想要的函数.我知道这一定很奇怪;嵌套的无限循环听起来像废话,哈哈.

Now, you'll notice I have to change the k value for different values. When the arguments z,l are further away from the real axis, we can make k very large (and we have to to get good accuracy), but it'll still overflow eventually; typically once we've achieved about 13-15 significant digits, is when the functions will start to blow up. You'll note, that setting k =60, means we're taking 60 logarithms. This already sounds like a bad idea, lol. Mathematically though, the value Abl_L(z,l,infinity,infinity) is precisely the function I want. I know that must be odd; nested infinite for-loops sounds like nonsense, lol.

我想知道是否有人能想出一种方法来避免这些溢出错误并获得更高的准确度.在一个完美的世界里,这个对象绝对是收敛的,而且这段代码是完美的(虽然可能有点慢);但我们可能需要无限期地增加堆栈大小.理论上,这完全没问题;但实际上,这不仅仅是不切实际的.无论如何,作为一名程序员,有没有办法解决这个问题?

I'm wondering if anyone can think of a way to avoid these overflow errors and obtaining a higher degree of accuracy. In a perfect world, this object most definitely converges, and this code is flawless (albeit, it may be a little slow); but we'd probably need to increase the stacksize indefinitely. In theory this is perfectly fine; but in reality, it's more than impractical. Is there anyway, as a programmer, one can work around this?

此时我唯一的另一个选择是尝试创建一个蛮力算法来发现这个函数的泰勒级数;但我做这件事的运气并不好.这个过程非常独特,尝试使用泰勒级数解决这个问题有点让我们回到原点.除非,这里有人能想到从这个表达式中恢复泰勒级数的奇特方法.

The only other option I have at this point is to try and create a bruteforce algorithm to discover the Taylor series of this function; but I'm having less than no luck at doing this. The process is very unique, and trying to solve this problem using Taylor series kind of takes us back to square one. Unless, someone here can think of a fancy way of recovering Taylor series from this expression.

老实说,我愿意接受所有建议和意见.我不知所措;我想知道这是否只是唯一解决方案是无限期增加堆栈大小的事情之一(这绝对有效).这不仅仅是因为我要处理大量的数字.这是我需要越来越大的值来计算一个小的值.出于这个原因,我想知道是否有一些我没有看到的快速工作.Pari-GP 吐出的错误总是与 tau_K 一起出现,所以我想知道这是否是次优编码;并且我应该向它添加一些东西以减少迭代时的堆栈大小.或者,如果这甚至可能的话.再说一次,我是一个糟糕的程序员.我需要有人向我解释这一点,就像我在幼儿园一样.

I'm open to all suggestions, any comments, honestly. I'm at my wits end; and I'm wondering if this is just one of those things where the only solution is to increase the stacksize indefinitely (which will absolutely work). It's not just that I'm dealing with large numbers. It's that I need larger and larger values to compute a small value. For that reason, I wonder if there's some kind of quick work around I'm not seeing. The error Pari-GP spits out is always with tau_K, so I'm wondering if this has been coded suboptimally; and that I should add something to it to reduce stacksize as it iterates. Or, if that's even possible. Again, I'm a horrible programmer. I need someone to explain this to me like I'm in kindergarten.

非常欢迎任何帮助、评论、澄清问题.此刻我就像一条追尾的狗;想知道他为什么不能取 1000 个对数,哈哈.

Any help, comments, questions for clarification, are more than welcome. I'm like a dog chasing his tail at this point; wondering why he can't take 1000 logarithms, lol.

问候.

我想我会补充一点,我可以产生任意精度,但我们必须将 z 的参数远离左半平面.如果变量 n,k = -real(z) 那么我们可以通过将 n 设置为我们想要的大小来产生任意精度.这里有一些输出来解释这一点,其中我使用了 \p 200 并且我们在这个级别几乎已经相等(减去一些数字).

I thought I'd add in that I can produce arbitrary precision but we have to keep the argument of z way off in the left half plane. If the variables n,k = -real(z) then we can produce arbitrary accuracy by making n as large as we want. Here's some output to explain this, where I've used \p 200 and we pretty much have equality at this level (minus some digits).

Abl_L(-1000,1+I,1000,1000)

%16 = -0.29532276871494189936534470547577975723321944770194434340228137221059739121428422475938130544369331383702421911689967920679087535009910425871326862226131457477211238400580694414163545689138863426335946 + 1.5986481048938885384507658431034702033660039263036525275298731995537068062017849201570422126715147679264813047746465919488794895784667843154275008585688490133825421586142532469402244721785671947462053*I

exp(Abl_L(-1001,1+I,1000,1000))

%17 = -0.29532276871494189936534470547577975723321944770194434340228137221059739121428422475938130544369331383702421911689967920679087535009910425871326862226131457477211238400580694414163545689138863426335945 + 1.5986481048938885384507658431034702033660039263036525275298731995537068062017849201570422126715147679264813047746465919488794895784667843154275008585688490133825421586142532469402244721785671947462053*I

Abl_L(-900 + 2*I, log(2) + 3*I,900,900)

%18 = 0.20353875452777667678084511743583613390002687634123569448354843781494362200997943624836883436552749978073278597542986537166527005507457802227019178454911106220050245899257485038491446550396897420145640 - 5.0331931122239257925629364016676903584393129868620886431850253696250415005420068629776255235599535892051199267683839967636562292529054669236477082528566454129529102224074017515566663538666679347982267*I

exp(Abl_L(-901+2*I,log(2) + 3*I,900,900))

%19 = 0.20353875452777667678084511743583613390002687634123569448354843781494362200997943624836883436552749978073278597542986537166527005507457802227019178454911106220050245980468697844651953381258310669530583 - 5.0331931122239257925629364016676903584393129868620886431850253696250415005420068629776255235599535892051199267683839967636562292529054669236477082528566454129529102221938340371793896394856865112060084*I

Abl_L(-967 -200*I,12 + 5*I,600,600)

%20 = -0.27654907399026253909314469851908124578844308887705076177457491260312326399816915518145788812138543930757803667195961206089367474489771076618495231437711085298551748942104123736438439579713006923910623 - 1.6112686617153127854042520499848670075221756090591592745779176831161238110695974282839335636124974589920150876805977093815716044137123254329208112200116893459086654166069454464903158662028146092983832*I

exp(Abl_L(-968 -200*I,12 + 5*I,600,600))

%21 = -0.27654907399026253909314469851908124578844308887705076177457491260312326399816915518145788812138543930757803667195961206089367474489771076618495231437711085298551748942104123731995533634133194224880928 - 1.6112686617153127854042520499848670075221756090591592745779176831161238110695974282839335636124974589920150876805977093815716044137123254329208112200116893459086654166069454464833417170799085356582884*I

问题是,我们不能只是一遍遍地应用 exp 来继续前进并期望保持相同的精度.问题在于 exp,当您在复平面中对其进行迭代时,它会显示出如此多的混乱行为,这注定会起作用.

The trouble is, we can't just apply exp over and over to go forward and expect to keep the same precision. The trouble is with exp, which displays so much chaotic behaviour as you iterate it in the complex plane, that this is doomed to work.

推荐答案

好吧,我回答了我自己的问题.@user207421 发表了评论,我不确定这是否意味着我认为的意思,但我认为它让我到达了我想要的地方.我有点假设 exp 不会继承其参数的精度,但显然这是真的.所以我只需要定义,

Well, I answered my own question. @user207421 posted a comment, and I'm not sure if it meant what I thought it meant, but I think it got me to where I want. I sort of assumed that exp wouldn't inherit the precision of its argument, but apparently that's true. So all I needed was to define,

Abl_L(z,l,n,k) ={
    if(real(z) <= -max(n,k),
    beta_function(z,l,n) + tau_K(z,l,n,k),
    exp(Abl_L(z-1,l,n,k)));
}

从这里开始一切正常;当然,为了我需要它.所以,我回答了我自己的问题,这很简单.我只需要一个 if 语句.

Everything works perfectly fine from here; of course, for what I need it for. So, I answered my own question, and it was pretty simple. I just needed an if statement.

无论如何,感谢所有阅读本文的人.

Thanks anyway, to anyone who read this.

这篇关于有没有更有效的对数嵌套方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆