if and logical connectives

3

I need to find the least number and the second smallest number of five numbers entered.

But this strange fact is happening:

#Subtrair o menor numero encontrado do numero digitado
dif1 = n1 - menor
dif2 = n2 - menor
dif3 = n3 - menor
dif4 = n4 - menor
dif5 = n5 - menor

#O menor resultado diferente de zero é o segundo menor numero
print(dif1, dif2, dif3, dif4, dif5)

#O erro se encontra aqui!
if (dif1>0) & (dif1<dif2) & (dif1<dif3) & (dif1<dif4) & (dif1<dif5):
    print("n1 é o segundo menor numero")

if (dif2>0) & ((dif2<dif1) & (dif2<dif3) & (dif2<dif4) & (dif2<dif5)):
    print("n2 é o segundo menor numero")

if (dif3>0) & ((dif3<dif2) & (dif3<dif1) & (dif3<dif4) & (dif3<dif5)):
    print("n3 é o segundo menor numero")

if (dif4>0) & ((dif4<dif2) & (dif4<dif3) & (dif4<dif1) & (dif4<dif5)):
    print("n4 é o segundo menor numero")

if (dif5>0) & ((dif5<dif2) & (dif5<dif3) & (dif5<dif4) & (dif5<dif1)):
    print("n5 é o segundo menor numero")


print(menor)

If I declare only

if (dif1>0):
...
.

The print message is executed on the screen. Likewise if I declare:

if (dif1<dif2) & (dif1<dif3) & (dif1<dif4) & (dif1<dif5):
..
.

But if I declare the sentence complete:

if (dif1>0) & (dif1<dif2) & (dif1<dif3) & (dif1<dif4) & (dif1<dif5):
..
.

The print message does not appear in any way! I also tried with if(dif1!=0) and other combination of relatives and nothing. And anyway the terminal does not show any error.

Could anyone tell me why?

PS: It seems to me that this case also happens in other languages.

    
asked by anonymous 23.05.2018 / 12:09

3 answers

6

In Python there is no goofy syntax !

You can use the nlargest() function of the default library heapq , see:

import heapq

lista = [ 9, 6, 3, 5, 0, 7, 8, 2, 1, 4 ]

maiores = heapq.nlargest( 2, lista )

print(maiores)

Output:

[9, 8]

A workaround is to sort the list in descending order using the sorted() function and use slice notation to extract the first two elements:

lista = [ 9, 6 , 3, 5, 0, 7, 8, 2, 1, 4 ]

lstord = sorted( lista, reverse=True ) # Ordena a lista em ordem reversa

maiores = lstord[:2] # extrai apenas os dois primeiros elementos da lista

print( maiores )

Output:

[9, 8]
    
23.05.2018 / 12:29
5
  

PS: It seems to me that this case also happens in other languages.

It is not a problem in language, but in its logic. The idea that you used is very interesting, to subtract the smallest number and to check again the minor among them that is not zero, however, its conditions will never be satisfied by the fact that one of the differences will be zero.

To better explain, let's assume the entries:

n1 = 3
n2 = 5
n3 = 1
n4 = 6
n5 = 2

Thus, the smallest value will be n3 , so menor = 1 . After this, you subtract from all values the smallest:

#Subtrair o menor numero encontrado do numero digitado
dif1 = n1 - menor  # 2
dif2 = n2 - menor  # 4 
dif3 = n3 - menor  # 0
dif4 = n4 - menor  # 5
dif5 = n5 - menor  # 1

You do this exactly with the intention of looking again for the smallest number between dif1 , dif2 , dif3 , dif4 and dif5 , other than zero. That is, it would be expected to indicate n5 as the second smallest number, since it is the smallest non-zero difference. Therefore, you would be expected to display the message:

if (dif5>0) & ((dif5<dif2) & (dif5<dif3) & (dif5<dif4) & (dif5<dif1)):
    print("n5 é o segundo menor numero")

But here you check that dif5 is less than dif3 , which is zero. In other words, any of the differences will always be zero, and so the difference in the second smaller number will never be the smallest difference, which explains why the second lowest number message is never displayed. In this case, you would have to check each difference value if it is not zero, to disregard the one referring to the smallest number; its condition would be gigantic, unreadable (more so) and unfeasible to use.

Another way would be, like Lacobus commented in your answer, use the heapq.nsmallest ( nlargest for the largest numbers):

dois_menores = heapq.nsmallest(2, [n1, n2, n3, n4, n5])

However, this form is equivalent to you ordering the list and returning the first two values, which I think is even more readable:

dois_menores = sorted([n1, n2, n3, n4, n5])[:2]

Or, implement a function that iterates your list of numbers by checking which two are smaller:

def retorna_dois_menores(numeros):
     m1, m2 = float('inf'), float('inf')
     for x in numeros:
         if x <= m1:
             m1, m2 = x, m1
         elif x < m2:
             m2 = x
     return m1, m2

dois_menores = retorna_dois_menores([n1, n2, n3, n4, n5])

Adapted from How to find the second lowest value of a python array without using built-in functions?

    
23.05.2018 / 13:24
2

As tagged

23.05.2018 / 14:01