
Help please write on si. It seems not difficult, but I don’t have any problems with math.
Well, look.
To begin with, your amount is incorrectly disclosed: for n = 0 we have x^0 / 0! , i.e. 1 , not x .
So, the initial value of the term is 1 . To go to the new term on the ith iteration, it is necessary to multiply by x^2 and divide by (2*i - 1) * (2 * i) . Further clear?
By the way, exponentiation is not necessary, if done, as described.
On the other hand, it is known that, for better accuracy of calculations, it is necessary to begin the summation with the smallest modulo numbers. That is, to consider better from the end . To do this, turn one cycle into two:
i = 0 , x = 1 until |x| >= eps |x| >= eps increase i , x multiply by x0 * x0 and divide by (2*i - 1) * (2 * i)i >= 0 increase the sum by x , divide x by x0 * x0 and multiply by (2*i - 1) * (2 * i) , decrease iAs correctly noted in the comments, calculating the terms twice (once on the way to the right, and once on the way to the left), we lose accuracy. The solution is to memorize the calculated elements (for this, it would be nice to have an automatically growing container, like std::vector in C ++), or to do three passes: one to calculate the number of terms, the second to calculate the terms themselves and remember them, the third to sum up from the end. Instead of the first pass, it is possible, in theory, to roughly estimate the number of items by the exit condition ( |x|^n/n! < eps <=> n ln |x| - ln n! < ln eps ), using the Stirling formula .
@VlaD , comments are over, I decided to lay out an example on python
# решение в лоб, суммируем слева направо def check(x = 0, eps = 0): sumPart = 1. curSum = 0 n = 1 while sumPart > eps: curSum += sumPart sumPart = sumPart * x * x / (n * (n + 1)) n += 2 return curSum # решение через рекурсию (по формуле @dzhioev ), суммирование справа налево def calc(x = 0, eps = 0, n = 1, mulPart = 1): sumPart = 1. * (x * x) / (n * (n + 1)) stepSum = mulPart * sumPart if stepSum < eps: return 1 return 1 + sumPart * calc(x, eps, n + 2, stepSum) # хвостовая рекурсия, суммирование слева направо def tailLRSum(x = 0, eps = 0, n = 1, mulPart = 1, result = 1): currentSumPart = 1. * (x * x) / (n * (n + 1)) stepSum = mulPart * currentSumPart if stepSum < eps: return result return tailLRSum(x, eps, n + 2, stepSum, result + stepSum) # хвостовая рекурсия, суммирование справа налево (используем lambda) def tailRLSum(x = 0, eps = 0, n = 1, mulPart = 1, result = None): sumPart = 1. * (x * x) / (n * (n + 1)) stepSum = mulPart * sumPart if result == None: result = lambda value: value if stepSum < eps: return result(0) return tailRLSum(x, eps, n + 2, stepSum, lambda value: result(1 + sumPart * value)) As you can see - each method gives its results.
The first three are almost the same, but the last one behaves strangely - its accuracy is not eps, but 10 * eps. Those. if he is checked if if stepSum <eps * 0.1, then the accuracy will be what is needed (output in brackets). And in this case (ie, with eps * 0.1), the accuracy will be higher than that of the others.
For myself, I realized that I don’t know how everything works inside. After all, in fact (at least for me), the second and fourth options should be worked out in the same way - first, the right terms are calculated, then the left ones are added. Similarly, the first and second - first calculated the left, then the right terms. But it can be seen in some place (for me not obvious) there is a loss of accuracy. And somewhere in the last method, in general, something not good is going on ...
As for arbitrary tail recursion, give an example - I will look, and I will not say anything, because I do not know.
Is there anyone who can comment on the results?
Method of nesting procedures
x^2n / (2n)! < eps x^2n / (2n)! < eps . - VladDSource: https://ru.stackoverflow.com/questions/223615/
All Articles