Le plus grand nombre impair

Aug 19 2020

Demandez à l'utilisateur de saisir 10 entiers, puis d'imprimer le plus grand nombre impair entré. Si aucun nombre impair n'a été entré, imprimez un message à cet effet.

J'ai essayé de résoudre ce problème avec python et je pense avoir trouvé un moyen qui couvre tous les cas possibles étant donné la définition mathématique d'un nombre impair. Pour être sûr, je voudrais vérifier si mon code est correct compte tenu de vos propres critères.

counter = 0
odd = []

while counter < 10:
    x = int(input("Enter a number: "))
    if abs(x)%2 != 0:
        odd.append(x)
    counter += 1

if len(odd) == 0:
    print("No odd number was entered")
else:
    print("The largest odd number is:", max(odd))

Réponses

19 MarioIshac Aug 19 2020 at 07:14

Pour votre programme actuel, nous pouvons améliorer plusieurs choses:

  1. Renommez odden odds(puisqu'il s'agit d'un list).
  2. Utilisez à la not oddsplace de len(odds) == 0(voir Comment vérifier si une liste est vide? Pour une raison pour laquelle cela est préféré).
  3. Supprimer counter. Puisque nous n'utilisons que counterdans la whilecondition, nous pouvons en fait remplacer le tout whilepar for _ in range(10).
  4. Suivez PEP 8 . Par exemple, en utilisant 4 espaces pour chaque niveau d'indentation.

En tenant compte de tous ces changements, nous obtenons:

odds = []

for _ in range(10):
    x = int(input("Enter a number: "))
    if abs(x) % 2 != 0:
        odds.append(x)

if not odds:
    print("No odd number was entered")
else:
    print("The largest odd number is:", max(odds))

Mais nous pouvons également améliorer l'efficacité de ce programme. À l'heure actuelle, nous gardons une trace de tous les nombres impairs, avant de choisir le maximum. Cela signifie que la complexité spatiale est O (N). Nous pouvons changer cela en O (1) en gardant une trace du plus grand nombre impair comme ceci:

max_odd = None

for _ in range(10):
    x = int(input("Enter a number: "))

    if abs(x) % 2 != 0:
        max_odd = x if max_odd is None else max(max_odd, x)

if max_odd is None:
    print("No odd number was entered")
else:
    print("The largest odd number is: ", max_odd)

Notez que nous utilisons Nonepour signifier qu'aucun nombre impair a été saisi jusqu'à présent, dans ce cas , sur un nombre impair étant entré nous avons mis max_oddà xdirectement. Sinon, nous nous sommes mis max_oddà max(max_odd, x).

Pour ce type de programme, vous ne remarquerez pas l'augmentation de l'efficacité due à la réduction de la complexité de l'espace. Mais apprendre à reconnaître où ces réductions sont possibles vous permettra de voir les mêmes modèles dans les programmes où cela compte.

Il y a enfin une chose que vous pouvez faire. Si vous voulez permettre au programme de continuer à accumuler des nombres dans le cas où un strest accidentellement tapé qui ne peut pas être analysé comme un nombre (tel que ""), nous pouvons utiliser un try/ exceptenveloppé dans un whilecomme ceci:

while True:
    try:
        x = int(input("Enter a number: "))
        break
    except ValueError:
        continue

Cela remplacerait:

x = int(input("Enter a number: "))

dans le code d'origine. Cela continuerait à inviter l'utilisateur à taper un strqui est analysable comme un intjusqu'à ce qu'il le fasse. Étant donné que tout se passe dans la même itération du for, le nombre de nombres qu'ils peuvent saisir (10 dans notre cas) ne serait pas réduit.

6 GZ0 Aug 19 2020 at 08:58

Ajout à l'avis précédent:

  • Quand xest un entier, abs(x) % 2équivaut à x % 2en Python. La sortie de l'opérateur modulo %a le même signe que le deuxième opérande.
  • Lorsque vous exécutez du code en dehors d'une méthode / classe, il est recommandé de placer le code dans un garde principal . Voir ici pour plus d'explications.

Dans Python 3.8, le code peut être raccourci en utilisant l'opérateur d'affectation :=avec la maxfonction.

if __name__ == "__main__":
    # Number generator
    num_gen = (o for _ in range(10) if (o := int(input("Enter a number: "))) % 2 != 0)
    max_odd = max(num_gen, default=None)
    if max_odd is None:
        print("No odd number was entered")
    else:
        print(f"The largest odd number is: {max_odd}")

L'emballage int(input("Enter a number: "))dans une fonction offre une meilleure lisibilité:

def read_input() -> int:
    return int(input("Enter a number: "))

if __name__ == "__main__":
    num_gen = (o for _ in range(10) if (o := read_input()) % 2 != 0)
    max_odd = max(num_gen, default=None)
    if max_odd is None:
        print("No odd number was entered")
    else:
        print(f"The largest odd number is: {max_odd}")

Une autre variante qui gère les entrées utilisateur non valides est la suivante:

def read_input() -> int:
    while True:
        try:
            return int(input("Enter a number: "))
        except ValueError:
            continue

if __name__ == "__main__":
    try:
        max_odd = max(o for _ in range(10) if (o := read_input()) % 2 != 0)
        print(f"The largest odd number is: {max_odd}")
    except ValueError:
        # Since read_input() no longer raises ValueError, the except
        # statement here only handles the cases where max() gets no inputs
        print("No odd number was entered")
3 AlexeyBurdin Aug 19 2020 at 12:56

Puis-je vous demander quel langage de programmation avez-vous pratiqué avant python?
Je veux mentionner un one-liner pour cela:

max(l,key=lambda x:(x%2,x))

en supposant que vous avez déjà lentré d'une manière ou d'une autre, comme

s='Enter a number: '
l=[int(input(s)) for i in range(10)]

Comment fonctionne le code? Il cherche au maximum key(x)pour xen let retourne tel x. La clé ici est la fonction lambda qui renvoie tuple (1,x)pour impair xet (0,x)pour pair x. Les tuples sont comparés de gauche à droite, par exemple (1,x)>(0,y)pour chaque xet y. Donc nous disons simplement "donnez-moi le maximum de l, en supposant qu'un nombre impair est toujours plus grand qu'un nombre pair".

Donc tout le programme ressemblera à

s='Enter a number: '
l=[int(input(s)) for i in range(10)]
m=max(l,key=lambda x:(x%2,x))
if m%2:
    print('The largest odd number is: %d'%m)
else: #the greatest is even, therefore no odd numbers
    print('No odd number was entered')

Court, sympa et facile, comme python.

Mais je suis d'accord qu'un bloc try-except autour de int(input())la réponse acceptée est utile, sans pré-stockage de la liste entière des valeurs impaires.

Je voulais seulement démontrer le paradigme de la programmation fonctionnelle en python, lorsque vous dites simplement à python «Je veux que cela soit fait (par exemple, une valeur maximale)» et qu'il le fait pour vous, vous n'avez pas besoin d'expliquer comment il doit le faire.

Merci d'avoir lu.

3 EmilioMBumachar Aug 19 2020 at 21:36

Je vais essayer de m'appuyer sur la dernière suggestion de la réponse acceptée.

while True:
    try:
        x = int(input("Enter a number: "))
        break
    except ValueError:
        continue

J'approuve définitivement cette suggestion, elle permet à votre programme de gérer les entrées invalides avec élégance au lieu de simplement planter.

Cependant, cela crée un problème d'utilisabilité. L'utilisateur qui vient de taper une lettre dans un nombre ne l'a probablement pas remarqué. Ils penseront qu'ils ont obtenu le numéro prévu, passeront au suivant, puis seront confus à la fin, lorsqu'ils penseront avoir tous les chiffres, mais l'ordinateur demande toujours le suivant.

Mieux vaut leur donner un feedback:

while True:
    try:
        x = int(input("Enter a number: "))
        break
    except ValueError:
        print("Invalid number will be ignored.")
        continue

... ou encore mieux, imprimez leur numéro tapé sur eux:

while True:
    try:
        inputString = input("Enter a number: ")
        x = int(inputString)
        break
    except ValueError:
        print("Invalid number will be ignored: {}".format(inputString))
        continue

J'envisagerais également de conserver la liste complète des numéros valides saisis, pas seulement les numéros impairs, et de les imprimer tous à l'utilisateur avant le résultat, pour lui donner une dernière chance de repérer les fautes de frappe. Ils peuvent, après tout, avoir mal saisi un numéro valide mais involontaire. Notez que cela augmenterait l'utilisation de la mémoire et que certains considéreraient cela comme une sur-communication.

print("Numbers provided are: {}".format(all_valid_numbers_inputted))
if not odds:
    print("No odd number was entered")
else:
    print("The largest odd number is:", max(odds))

Si vous faites cela, la prochaine étape serait de vous débarrasser de la variable "odds" et de déterminer la plus grande cote directement à partir de la liste complète.

1 FMc Aug 25 2020 at 12:23

Le point clé ici: chaque étape du processus ne fait qu'une chose simple. Vous construisez des programmes de cette façon - une étape incrémentielle et étroitement définie à la fois. Ne mélangez pas tout dans un fouillis - par exemple une boucle où nous interagissons avec un utilisateur tout en effectuant les conversions et les calculs nécessaires plus tard.

def as_int(s):
    try:
        return int(s)
    except Exception:
        return 0

N = 3
MSG = 'Enter number: '

replies = [input(MSG) for _ in range(N)]  # Interact.
nums = [as_int(r) for r in replies]       # Convert.
odds = [n for n in nums if n % 2]         # Compute.

if odds:                                  # Report.
    print(max(odds))