Make a function that calculates the following sum:

Asked

Viewed 312 times

0

S = 10/1! - 9/2! + 8/3! ... - 1/10!

def soma():
    fat = 1
    somar = 0.0
    for i in range(1, 11):
        fat *= i
        for k in range(i, 0, -1):
            somar += k/fat
    return round(somar, 2)

I arrived at this code but the output is different than expected(6.59)

  • I believe this inner loop is doubling the sum of terms. Swap for k in range(i, 0, -1): somar += k/fat for: somar += (11-i) / fat.

  • 1

    Explain to me how the expected output can be 6.59 if 10/1! is equal to 10 ??? The result will certainly be greater than 10.

  • I realized now that there are signs of addition and subtraction. I was betrayed by the title of the question. So, 6.59 makes sense.

  • Typo: !3 -- 3!

5 answers

3

In cases like this, you could have done the table test, that would have easily noticed the problems of your code: you do not exchange the signal to switch between subtraction and sum, and the more internal loop is completely unnecessary.

You can do it like this:

def soma():
    fat = -1
    total = 0
    for i in range(1, 11):
        fat = -fat * i
        total += (11 - i) / fat
    return round(total, 2)

And only.


Other answers suggested having a function only to calculate the factorial, which also works, but in this case I find it unnecessary. For example, if in the middle of the calculation you have already made the factorial of 3, that means that you have already multiplied 1, 2 and 3. Then, in the next iteration you will have to calculate the factorial of 4, and multiply again 1, 2 and 3, to multiply by 4.

That is, several redundant and unnecessary multiplications will be made (this happens even if using the module’s ready function math, for in spite of her use a more efficient algorithm, still ends up having this unnecessary rework). One of the answers even suggests using recursion, which makes everything more inefficient yet (I know that factorial is often used as an example to teach recursion, but many forget to mention that it is not the most efficient way to do this calculation).

In the case of its calculation, simply multiply the last factorial found by the next number, and invert the signal so that it changes between the sum and the subtraction.


As a curiosity, it follows a comparison between the solutions: https://ideone.com/nyUKyd - notice how the recursive solution is slower (of course for small calculations performed a few times makes no difference, but it is important to pay attention to these details and do not quit using recursion where no need).

1

I hope the code below helps:

def fatorial(n):
    if n == 0 or n == 1:
        return 1
    return n * fatorial(n - 1)

NUMERO = 10
SOMA = True

num_dem = zip(reversed(range(1, NUMERO + 1)), range(1, NUMERO + 1))
S = 0
for num, dem in num_dem:
     fat = fatorial(dem)
     print(f"{num:5} {dem:5} {fat:7} {num/fat:.20f}")
     if SOMA:
         S += num/fat
     else:
         S -= num/fat
     SOMA = not SOMA

print(f"A soma é {S}")

The print will bring

   10     1       1 10.00000000000000000000
    9     2       2 4.50000000000000000000
    8     3       6 1.33333333333333325932
    7     4      24 0.29166666666666668517
    6     5     120 0.05000000000000000278
    5     6     720 0.00694444444444444406
    4     7    5040 0.00079365079365079365
    3     8   40320 0.00007440476190476191
    2     9  362880 0.00000551146384479718
    1    10 3628800 0.00000027557319223986

>>> print(f"A soma é {S}")
A soma é 6.58544670414462

NOTE: This reply was edited, because initially I had not realized that there was addition and subtraction.

I hope I’ve helped

1


To resolve this issue you can implement two functions. One of them to calculate the factorial of the number and another to produce the summation of values.

OBSERVATION 1: Observe the layout of the sequence of signs of ADDITION and SUBTRACTION.

The sequence we were given was: S = 10/1! - 9/2! + 8/3! - ... - 1/10!

Well, to resolve this issue we can implement the following code:

def somar(n):
    soma = cont = 0
    for c in range(n, 0, -1):
        cont += 1
        termo = (c / fatorial(cont))
        if cont % 2 == 0:
            soma -= termo
        else:
            soma += termo
    return round(soma, 2)


def fatorial(nu):
    prod = 1
    for i in range(nu, 0, -1):
        prod *= i
    return prod


num = int(input('Digite um número: '))

print(somar(num))

Note that when we execute this code we receive the following message: Digite um número: . At this point we must enter a integer and press enter.

After that, the entered value will be passed as parameter to the function sum(n). Getting there, every iteration of the block for, the term (c / factorial(cont)).

Observation 2: With each iteration, the block if will verify whether cont is even. Positive case, termo will be decreased by soma. Negative case, termo will be incrementado in soma.

Observation 3: Every iteration of the block for of function somar(n), will be called the function fatorial(nu) that calculates the factorial of the cont.

Then this term is accumulated in the variable summing up and subsequently the return of the function sum(n) will be shown.


Now, if you prefer, you can use the method factorial library Math. This way, the code would be:

from math import factorial

def somar(n):
    soma = cont = 0
    for c in range(n, 0, -1):
        cont += 1
        termo = (c / factorial(cont))
        if cont % 2 == 0:
            soma -= termo
        else:
            soma += termo
    return round(soma, 2)


num = int(input('Digite um número: '))

print(somar(num))

Another way more quick to calculate this sum is:

def somar(n):
    soma = cont = 0
    fat = 1
    for c in range(n, 0, -1):
        cont += 1
        fat *= cont
        termo = (c / fat)
        if cont % 2 == 0:
            soma -= termo
        else:
            soma += termo
    return round(soma, 2)


num = int(input('Digite um número: '))

print(somar(num))

Let’s test the codes?

After we run both codes, we can enter any integer numbers and press enter.

In case we enter the numbers 2, 3, 4 and 10 respectively, we will have the following results:

n = 2 = (2/1!) - (1/2!) = 1.5
n = 3 = (3/1!) - (2/2!) + (1/3!) = 2.17
n = 4 = (4/1!) - (3/2!) + (2/3!) - (1/4!) = 2.79
n = 10 = (10/1!) - (9/2!) + (8/3!) - (7/4!) + (6/5!) - (5/6!) + (4/7!) - (3/8!) + (2/9!) - (1/10!) = 6.59
  • @Marco Raad, test this solution.

  • 1

    It worked. I appreciate

  • @Marco Raad, Welcome to the platform! And, if the answer solved your problem, you can ACEITÁ-LA. See here how and why to accept. Although not mandatory, this practice is encouraged on the site, indicating to future visitors that such a response solved the problem. And when you have more than 15 reputation points, you can also vote in any useful responses.

1

Well, your sequence has changed a little by alternating sum and subtraction.
Here you have the calculation demonstration:
https://www.wolframalpha.com/input/? i=10%2F1%21+-+9%2F2%21+%2B+8%2F3%21+-+7%2F4%21+%2B+6%2F5%21+-+5%2F6%21+%2B+4%2F7%21+-+3%2F8%21+%2B+2%2F9%21+++-+1%2F10%21

As for your code, taking advantage of the characteristic of the problem and not calculating the whole factorial at a time, just add the signal alternation.

def soma():
    fat = 1
    sinal = 1
    somar = 0.0
    for i in range(1, 11):
        fat *= i
        somar += sinal * ((11-i) / fat)
        sinal = -sinal
    return round(somar, 2)
  • Running your code, I still have sequence output without subtraction

  • Corrected. Failed to consider the sign in accumulation.

0

Using lists in comprehension (or iterators in comprehension)

from math import factorial as fac

print(sum((11-x)/fac(x)*(1 if x%2 else -1) for x in range(1,11)))

Browser other questions tagged

You are not signed in. Login or sign up in order to post.