Page 1 of 1

Essai de codage d'un menu.

Unread postPosted: 02 Apr 2021, 16:47
by ggauny@live.fr
Bonjour à tous.

J'ai tenté d'écrire un programme qui édite un menu permettant des choix.

Code: Select all
# Essai de codage d'un menu.
# Largement et librement adapté des écrits de Mss cent20, Bisam et Adriweb.

# Tapez fcal() pour lancer le programme. (fcal() ie fonctions calendaires).
# Le programme retourne, quand c'est judicieux, un simple chiffre en seconde ligne du résultat.
# Il s'agit du jour de la semaine : 0 = dimanche... 6 = samedi.

# Exemple : 19 6 1988 ==> 2447332 et 0, (Le n° du jour julien, et le jour de la semaine afférent, ici 0 soit dimanche).

# Constantes :

TEXTE = ("Fonctions calendaires :")
TEXTE1 = ("Veuillez entrer votre choix : 1, 2, 3, 4 ou 0 => ")

P, I, = print, input


def fcal():
    P(TEXTE)
   
    P("1. Date vers JDN")
    P("2. JDN vers date")
    P("3. JDS, jour de la semaine")
    P("4. Menu")
    P("0. Sortie du programme")
   
    C = int(input(TEXTE1))
       
    if C==0:
        P("Fin")
    elif C==1:
        P("vous avez opté pour la fonction 1. Date vers JDN : tapez jdn(j,m,a) : => ")
    elif C==2:
        P("vous avez opté pour la fonction 2. JDN vers date : tapez j2d(jdn) : => ")
    elif C==3:
        P("vous avez opté pour la fonction 3. Jour de la semaine : tapez jdn(j,m,a) : => ")
    elif C==4:
        menu()

# Date calendaire d'un JDN donné.
# Validité du 01/01/-4712 au 31/12/9999.
# jdn signifie Julian Day Number en anglais soit : Numéro du jour Julien.

from math import *

def jdn(j,m,a):

    if (m)<3:
        a-=1; m+=12

    jd=(int(365.25*(a+4716) + int(30.6001*(m+1)) + j - 1524))

    s=2299160       # dernier jour du calendrier julien
    if jd > s:          # si oui, ajuster pour le calendrier grégorien

        jd = jd + 2 - int(a/100) + int(a/400)

    P(jd)   # n° du jour julien (julian day number en anglais d'où : jdn)
    P((jd+1) % 7)

def j2d(jdn):
   
    z=an=a=b=c=E=0
    d=j=m=an=s=0
    R=1
   
    if jdn<0 or jdn>5373484:
        raise Exception("jdn indéfini car hors limites de validité")
        #print("jdn indéfini car hors limites de validité")
       
       
    z=int(jdn)
             
    a=int((z-1867216.25)/36524.25)
    an=z+1+a-int(a/4)
         
    if z<2299161:
        an=z
               
    b=an+1524; c=int((b-122.1)/365.25);
    d= int(365.25*c); E=int((b-d)/30.6001);
     
    j=b-d-int(30.6001*E)
   
    if E<14:
        m=E-1
       
    if E==14 or E==15:
        m=E-13
       
    if m<3:
        an=c-4715
       
    if m>2:
        an=c-4716
           
       
    if an<0:
        R=-1
   
       
    s=R*(fabs(j)+ fabs(m/100)+ fabs(an/1000000))
    s=round(s,7)
   
    P(s)
    P((jdn+1) % 7)




Il faut taper fcal(), taper 2 et enfin j2d(1507900), par exemple, pour obtenir -22.05.0584 : 22 mai de l'année -584.
Je me demande si ma démarche est bonne, oui ça marche mais .....

Peut-être une astuce, un raccourci de programmation ? Si vous avez le temps.

Une question : pourquoi y a-t-il une petite étoile rouge quand je poste un message ?

Bonne journée.

Re: Essai de codage d'un menu.

Unread postPosted: 04 Apr 2021, 09:09
by Bisam
Merci pour la citation, mais elle était bien inutile : il est normal d'utiliser ce que tu viens d'apprendre.

PS : Pour forcer le forum à comprendre que le code que tu as posté dans les balises [code] est du Python, tu peux écrire [code=python] à la place et terminer comme d'habitude par [ㅤ/code]

Re: Essai de codage d'un menu.

Unread postPosted: 15 Sep 2021, 22:10
by rentech7289
Pour commencer, simplifions un peu le code:
Code: Select all
from math import *

est mal placée. Les lignes d'importations doivent être placées après la docstring du module et avant toute déclaration d'affectation. Dans le cas présent, entre les lignes 9 et 10.
Code: Select all
    C = int(input(TEXTE1))

n'est pas conseillé. Si TEXTE1 change de type, le cast plante..., préférer:
Code: Select all
    DATA = input(TEXTE1)  # integer
    C = int(DATA)

Il suffit de modifier le cast si le type de DATA change...
Code: Select all
    if jdn<0 or jdn>5373484:
        raise Exception("jdn indéfini car hors limites de validité")
        #print("jdn indéfini car hors limites de validité")

peut s'écrire:
Code: Select all
    if 0 < jdn < 5373484:
        # Tous les calculs des lignes 72 à 106

La levée d'une exception consomme beaucoup de ressources, le if est plus efficace: si le test échoue, le programme s'arrête...
Code: Select all
    d= int(365.25*c); E=int((b-d)/30.6001);

préférer:
Code: Select all
    d= int(365.25*c)
    E=int((b-d)/30.6001)

Code: Select all
    if E==14 or E==15:

peut s'écrire:
Code: Select all
    if 13 < E < 16:


Il y aurait beaucoup à ajouter: les variables s'écrivent avec des minuscules, les calculs manquent de lisibilité... Par exemple, ligne 102:
Code: Select all
    s=R*(fabs(j)+ fabs(m/100)+ fabs(an/1000000))

devient:
Code: Select all
    s = r * (fabs(j) + fabs(m/100) + fabs(an/1000000))

mais pour faire simple, la référence pour commencer à bien coder en python est la suivante:
https://www.python.org/dev/peps/pep-0008/
En anglais uniquement. Au besoin, il y a Google Traduction...

Re: Essai de codage d'un menu.

Unread postPosted: 16 Sep 2021, 09:54
by ggauny@live.fr
Merci beaucoup Monsieur,
Vos remarques me sont très utiles et je vais les mettre en application.

Bonne journée.
Gérard GAUNY.

Re: Essai de codage d'un menu.

Unread postPosted: 18 Sep 2021, 11:08
by Bisam
Pour tester l'appartenance à un petit nombre de valeurs, Python permet aussi une méthode simple : tester l'appartenance à un type énumérable (une liste, un tuple, un ensemble, un dictionnaire, etc...) Par exemple :
Code: Select all
if E in (14, 15):

C'est plus facile à lire, à comprendre et à modifier si nécessaire qu'une succession de or.

Re: Essai de codage d'un menu.

Unread postPosted: 18 Sep 2021, 22:19
by rentech7289
Je reconnais Bissam que tu as raison sur la méthode mais pas sur le fond. La recherche en question peut s'appliquer sur un jeu de données de taille conséquente... De plus dans le cas présent, les données ne pas énumérables. La méthode pythonesque d'intervalle
Code: Select all
if inf < valeur < sup
est plus efficace qu'un
Code: Select all
if valeur in range(inf, sup)
et surtout plus rapide parce qu'il n'y a que deux tests à effectuer. Si un range est utilisé, il lui faut construire le jeu de données avant de pouvoir y chercher la valeur. Dans le cas présent, il n'y a que deux valeurs entières consécutives. Un simple test d'intervalle est amplement suffisant...
La méthode est plutôt à conseiller sur un jeu de données qui ne peuvent pas se résumer à un test d'intervalle. L'exemple le plus fréquent étant justement un intervalle dans lequel une valeur a été retirée... Dans le cas de ce programme, on peut utiliser la méthode que tu cites pour la valeur finale de la date avec le jour de la semaine ou le mois en toutes lettres.
.

Re: Essai de codage d'un menu.

Unread postPosted: 19 Sep 2021, 13:24
by Bisam
Tu remarqueras que je n'avais pas comparé ma méthode à celle de la double inégalité que tu avais proposée, mais uniquement à la suite de or, et c'était volontaire. Je sais bien qu'il y a des cas où la double inégalité sera bien plus efficace.

Je voulais juste signaler qu'il est plus simple d'écrire :
Code: Select all
fruits = {"pomme", "poire", "abricot", "cerise"}
if aliment in fruits:
    compote = cuire(aliment)


plutôt que
Code: Select all
if aliment == "pomme" or aliment == "poire" or aliment == "abricot" or aliment == "cerise":
    compote = cuire(aliment)

même si en pratique, il va se passer exactement la même chose à l'exécution.

Re: Essai de codage d'un menu.

Unread postPosted: 19 Sep 2021, 13:53
by rentech7289
Entièrement d'accord avec toi. Les points que je voulais mettre en avant sont liés à range (dont le comportement est différent des types énumérables que tu as donné) et à la petite taille de la structure de données. Les types en questions (list, tuple, set, dict et autres collections) devant être implémentés avant utilisation sous peine de levée d'exception. Par conséquent, il n'y a pas de perte de temps lié à la construction du jeu de données nécessaire pour le test. L'autre point important étant le fait que cela facilite le travail du compilateur qui n'a que la référence (l'adresse) de la structure de données à utiliser pour le test. CQFD.