IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Nombre d'années bissextiles entre deux années


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut Nombre d'années bissextiles entre deux années
    Salut,

    1- Comment coderiez-vous une fonction qui calcule le nombre d'années bissextiles entre deux années a1 et a2 (non inclus) ?

    Bon voici une solution avec une boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def is_bissextile(annee):
        return annee % 4 == 0 and annee % 100 != 0 or annee % 400 == 0
     
    # Fonction avec une boucle
    def nbr_annees_bissextiles1(a1, a2):
        nbr_annees_bissextiles = 0
        for a in range(a1, a2):
            if is_bissextile(a):
                nbr_annees_bissextiles += 1
        return nbr_annees_bissextiles
    Mais une solution avec une formule serait plus rapide je pense... Et justement j'ai trouvé cette formule* :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    diff = a2 - a1    
    nbr_annees_bissextiles = math.trunc(diff / 4) - math.trunc(diff / 100) + math.trunc(diff / 400)
    Mais après quelques testes je me suis rendu compte que parfois elle donne un résultat erroné, dans ces cas-là il manque une année...

    Je pense que l'erreur vient de la partie math.trunc(diff / 4), tout va bien si le reste de la division vaut 0 mais sinon dans certains cas il faut compenser en ajoutant une année.

    Le tout étant de trouver la condition permettant de repérer ces cas, j'en ai trouvé une (cf. le code ci-dessous) qui semble fonctionner mais elle me semble compliquée, je me demande si il n'y a pas plus simple...

    Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def is_bissextile(annee):
        return annee % 4 == 0 and annee % 100 != 0 or annee % 400 == 0
     
    # Fonction sans boucle...
    def nbr_annees_bissextiles(a1, a2):
        diff = a2 - a1
        reste = diff % 4
        nbr_annees_bissextiles = diff // 4 - diff // 100 + diff // 400
     
        condition = reste != 0 and (is_bissextile(a1) or reste >= 2 and is_bissextile(
            a1 + 1) or reste == 3 and is_bissextile(a1 + 2))
     
        if condition:
            nbr_annees_bissextiles += 1
     
        return nbr_annees_bissextiles
    Est-ce qu'il y a plus simple tout étant aussi/plus rapide ?


    2- Comment coderiez-vous une fonction qui donne la liste des années bissextiles entre deux années a1 et a2 (non inclus) ?



    * En python pas besoin de la fonction math.trunc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    diff = a2 - a1    
    nbr_annees_bissextiles = diff // 4 - diff // 100 + diff // 400

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Citation Envoyé par Beginner. Voir le message

    2- Comment coderiez-vous une fonction qui donne la liste des années bissextiles entre deux années a1 et a2 (non inclus) ?
    Bon comme promis dans l'autre fil à binarygirl je poste une solution "faite maison" pour comparaison avec les solutions utilisant les modules natifs...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def is_bissextile(annee):
        return annee % 4 == 0 and annee % 100 != 0 or annee % 400 == 0
     
    def lst_annees_bissextiles(a1, a2):
        annees_bissextiles = []
        for a in range(a1, a2):
            if is_bissextile(a):
                annees_bissextiles.append(a)
        return annees_bissextiles
    Bon c'est un exercice à la base mais si ça se trouve (à vérifier...) cette solution est aussi/plus performante que les solutions utilisant les modules natifs...

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Bon comme promis dans l'autre fil à binarygirl je poste une solution "faite maison" pour comparaison avec les solutions utilisant les modules natifs...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def is_bissextile(annee):
        return annee % 4 == 0 and annee % 100 != 0 or annee % 400 == 0
     
    def lst_annees_bissextiles(a1, a2):
        annees_bissextiles = []
        for a in range(a1, a2):
            if is_bissextile(a):
                annees_bissextiles.append(a)
        return annees_bissextiles
    Bon c'est un exercice à la base mais si ça se trouve (à vérifier...) cette solution est aussi/plus performante que les solutions utilisant les modules natifs...
    On peut faire plus rapide :

    1- On utilise (au maximum 4 fois) la fonction is_bissextile * pour trouver la première année bissextile a_bissextile_1
    2- Ensuite on fait une boucle for avec un range(a_bissextile_1 +4, a2, 4)
    - Du coup un peu plus de 4 fois moins de tour de boucles
    - plus besoin de tester si l'année est multiple de 4 ce qui nous économise n fois l'évaluation de annee % 4 == 0 (n est une valeur entre a2-a1-1 et a2-a1-4)
    - on économise n appels de fonction (c'est une petite économie mais c'est une économie quand même)

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    def is_bissextile(annee):
        return  annee % 4 == 0 and (annee % 100 != 0 or annee % 400 == 0)
     
    def lst_annees_bissextiles2(a1, a2):
        annees_bissextiles = []
     
        # on cherche la première année bissextile...
        for a in range(a1, a1+4):
            if is_bissextile(a):
                annees_bissextiles.append(a)
                break
     
        # Maintenant on ne boucle que sur les années multiples de 4
        # à partir de a + 4
        for a in range(a + 4, a2, 4):        
            if a % 100 != 0 or a % 400 == 0:
                annees_bissextiles.append(a)
     
        return annees_bissextiles


    * On peut la rendre plus rapide simplement en ajoutant une parenthèse (cf. #20) ou on peut aussi utiliser cette version #17 qui est plus rapide)

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 743
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    On peut faire plus rapide
    Reste à savoir si le cas d'utilisation de cela sera de savoir si une année particulière est (ou pas) bissextile ou si on va tester un intervalle d'années consécutives. Car plus rapide qui ne sert jamais n'a pas trop de sens.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Beginner. Voir le message
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def lst_annees_bissextiles2(a1, a2):
        annees_bissextiles = []
     
        # on cherche la première année bissextile...
        for a in range(a1, a1+4):
            if is_bissextile(a):
                annees_bissextiles.append(a)
                break
     
        # Maintenant on ne boucle que sur les années multiples de 4
        # à partir de a + 4
        for a in range(a + 4, a2, 4):        
            if a % 100 != 0 or a % 400 == 0:
                annees_bissextiles.append(a)
     
        return annees_bissextiles
    Si on cherche la rapidité, on peut dès le départ essayer d'éviter les append à un élément sur une liste vide. Voire éviter les append tout court.
    Et de là on peut se demander alors pourquoi une liste quand un tuple suffit...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def lst_annees_bissextiles2(a1, a2):
    	# on cherche la première année bissextile...
    	for a in range(a1, a1+4):
    		if is_bissextile(a):
    			first=a
    			break
     
    	# Maintenant on ne boucle que sur les années multiples de 4
    	# à partir de a + 4
    	return (first, ) + tuple(x for x in range(a+4, a2, 4) if x%100 != 0 or x%400 == 0)
    Et on peut même mettre le "return" directement à la place du break (mais je trouve ça moins élégant).

    Et si on veut aller plus loin dans la rapidité, alors on se demandera si l'appelant a vraiment toujours besoin de toutes les années ou si par hasard il n'aurait pas besoin parfois de s'arrêter dès qu'une certaine année est trouvée.
    Ce qui amène alors à remplacer le tuple par un générateur...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def lst_annees_bissextiles2(a1, a2):
    	# on cherche la première année bissextile...
    	for a in range(a1, a1+4):
    		if is_bissextile(a):
    			yield a
    			break
     
    	# Maintenant on ne boucle que sur les années multiples de 4
    	# à partir de a + 4
    	yield from (x for x in range(a+4, a2, 4) if x%100 != 0 or x%400 == 0)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Beginner. et Sve@r, attention que 7 années consécutives peuvent s'écouler sans année bissextile, par exemple de 2097 à 2103. Donc range(a1, a1+4) risque de ne pas avoir d'année bissextile.

    Voici un code qui marche, en une ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def lst_annees_bissextiles(a1, a2):
        return [a for a in range(((a1+3)//4)*4, a2, 4) if a % 100 != 0 or a % 400 == 0]
    Pareil avec un générateur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def annees_bissextiles(a1, a2):
        return (a for a in range(((a1+3)//4)*4, a2, 4) if a % 100 != 0 or a % 400 == 0)
    ((a1+3)//4)*4 est le plus petit multiple de 4 supérieur ou égal à a1.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    Beginner. et Sve@r, attention que 7 années consécutives peuvent s'écouler sans année bissextile, par exemple de 2097 à 2103. Donc range(a1, a1+4) risque de ne pas avoir d'année bissextile.
    Ah c'est vrai, le fameux "cas de merde" qui fait tout planter.
    Mais t'as raison, c'était bien de me le rappeler
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Salut,


    Citation Envoyé par Sve@r Voir le message
    Si on cherche la rapidité, on peut dès le départ essayer d'éviter les append à un élément sur une liste vide. Voire éviter les append tout court.
    Bonne idée...

    Citation Envoyé par Sve@r Voir le message
    Et de là on peut se demander alors pourquoi une liste quand un tuple suffit...
    Une liste c'est plus gourmand qu'un tuple ?

    Citation Envoyé par Sve@r Voir le message
    Ce qui amène alors à remplacer le tuple par un générateur...
    Merci, je ne connais pas encore yield , cela me fera un exemple d'utilisation si j'étudie ce point en python...

    Citation Envoyé par Pyramidev Voir le message
    Beginner. et Sve@r, attention que 7 années consécutives peuvent s'écouler sans année bissextile, par exemple de 2097 à 2103. Donc range(a1, a1+4) risque de ne pas avoir d'année bissextile.
    Ah oui décidément, ça fait la deuxième fois... Merci.


    Citation Envoyé par Pyramidev Voir le message
    Voici un code qui marche, en une ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def lst_annees_bissextiles(a1, a2):
        return [a for a in range(((a1+3)//4)*4, a2, 4) if a % 100 != 0 or a % 400 == 0]
    Pareil avec un générateur :
    Ah oui bien vu pour le ((a1+3)//4)*4.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Une liste c'est plus gourmand qu'un tuple ?
    Ben... un outil Y qui fait pareil que l'outil X et qui fait aussi des trucs en plus me semble plus gourmand (question de logique).
    Dans mon tuto j'explique d'abord les tuples, indiquant que cela permet d'associer et récupérer des ensembles d'éléments, puis je parle ensuite des listes en les présentant simplement comme des tuples modifiables.

    Swinnen, dans son tuto, parle d'abord des listes puis plus tard (bien plus tard) parle des tuples. Mais quand il en parle, lui aussi il dit que c'est plus économique que les listes et que si le truc n'a pas besoin d'être modifié alors il faut préférer le tuple aux listes.

    Citation Envoyé par Beginner. Voir le message
    Merci, je ne connais pas encore yield , cela me fera un exemple d'utilisation si j'étudie ce point en python...
    Un truc bien bien pratique (chapitre des générateurs).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Le tout étant de trouver la condition permettant de repérer ces cas, j'en ai trouvé une (cf. le code ci-dessous) qui semble fonctionner mais elle me semble compliquée, je me demande si il n'y a pas plus simple...

    Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def is_bissextile(annee):
        return annee % 4 == 0 and annee % 100 != 0 or annee % 400 == 0
     
    # Fonction sans boucle...
    def nbr_annees_bissextiles(a1, a2):
        diff = a2 - a1
        reste = diff % 4
        nbr_annees_bissextiles = diff // 4 - diff // 100 + diff // 400
     
        condition = reste != 0 and (is_bissextile(a1) or reste >= 2 and is_bissextile(
            a1 + 1) or reste == 3 and is_bissextile(a1 + 2))
     
        if condition:
            nbr_annees_bissextiles += 1
     
        return nbr_annees_bissextiles
    Est-ce qu'il y a plus simple tout étant aussi/plus rapide ?
    Hélas, ce code ne fonctionne pas, car nbr_annees_bissextiles(2097, 2103) retourne 1 avec ce code alors qu'il doit retourner 0. Je pense qu'une solution optimisée et qui marche sera plus compliquée que ce code.

    Sur une durée de 400 ans, il y aura toujours 97 années bissextiles. Mais, sur une durée de 5 à 7 ans, il peut y avoir 0, 1 ou 2 années bissextiles.

    Edit 1 : Voici une piste qui me vient à l'esprit pour construire l'algorithme :

    1. Se ramener au cas où l'écart entre les deux années est inférieur à 400. nbr_annees_bissextiles(a1, a4) == nbr_annees_bissextiles(a1, a3) + (a4 - a3) * 97 / 400 avec a3 - a1 < 400 et a4 - a3 qui serait multiple de 400.
    2. Se ramener au cas où l'écart entre les deux années est inférieur à 4. nbr_annees_bissextiles(a1, a3) == nbr_annees_bissextiles(a1, a2) + (a3 - a2) / 4 - x avec a2 - a1 < 4 et a3 - a2 qui serait multiple de 4. x serait un nombre entre 0 et 3 et correspondrait au nombre d'années multiples de 100 sans être multiples de 400 dans l'intervalle [a2, a3[. Pour évaluer x, il faudra tenir compte à la fois de a2 // 100 et a3 // 100. Il y aura des if.
    3. Calculer nbr_annees_bissextiles(a1, a2) en faisant une simple boucle. a2 - a1 < 4 donc ce sera court.

    Peut-être qu'il existe une démarche plus simple.

    Edit 2 : Je viens de poser la question à ChatGPT :

    Citation Envoyé par Pyramidev
    In Python, write a code which counts the number of leap years between two dates.
    Citation Envoyé par Pyramidev
    Can you write a more efficient code?
    Et il m'a répondu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def count_leap_years(year1, year2):
        return (year2 // 4) - (year1 // 4) - ((year2 // 100) - (year1 // 100)) + ((year2 // 400) - (year1 // 400))
    On peut aussi l'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def count_leap_years(year1, year2):
        return (year2 // 4) - (year1 // 4) - (year2 // 100) + (year1 // 100) + (year2 // 400) - (year1 // 400)
    La logique de cet algorithme s'appuie sur le fait que count_leap_years(year1, year2) == count_leap_years(0, year2) - count_leap_years(0, year1).

    Par contre, c'est pour l'intervalle ]year1, year2], alors que tu veux l'intervalle [a1, a2[. Donc il faudra faire un décalage d'indice :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def nbr_annees_bissextiles(a1, a2):
        year1 = a1 - 1
        year2 = a2 - 1
        return (year2 // 4) - (year1 // 4) - (year2 // 100) + (year1 // 100) + (year2 // 400) - (year1 // 400)

  11. #11
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Salut,

    Merci et bien vu pour la formule.

    J'ai fini aussi par trouver la formule que tu as postée à la fin mais j'ai fait mes tests en JS :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let a1_moin1 = a1 - 1, a2_moin1 = a2 - 1
    let annee_4 = Math.trunc(a2_moin1 / 4) - Math.trunc(a1_moin1 / 4)
    let annee_100 = Math.trunc(a2_moin1 / 100) - Math.trunc(a1_moin1 / 100)
    let annee_400 = Math.trunc(a2_moin1 / 400) - Math.trunc(a1_moin1 / 400)

    J’essaierais de comprendre l'explication que tu as donnée mais me concernant c'est toi qui m'as mis la puce à l'oreille...

    Oui car avant tes EDIT j'avais lu ce passage :

    Citation Envoyé par Pyramidev Voir le message
    Hélas, ce code ne fonctionne pas, car nbr_annees_bissextiles(2097, 2103) retourne 1 avec ce code alors qu'il doit retourner 0. Je pense qu'une solution optimisée et qui marche sera plus compliquée que ce code.
    C'est ce qui m'a fait comprendre qu'il fallait aussi compenser le terme diff // 100 dans certains cas et du coup je me suis dit que pour les mêmes raisons il fallait aussi compenser le terme diff // 400 dans certains cas...

    J'avais déjà trouvé une condition pour repérer les cas où il fallait compenser le terme diff // 4 mais trouver une formule pour avoir directement (par calcul et sans tester une condition) le nombre d'années multiples de 100 était plus facile, oui parce que : (year2 // 100) - (year1 // 100) avec year1 = a1 - 1 et year2 = a2 - 1 c'est en fait le nombre exacte d'années multiples de 100 qu'il y a dans l'intervalle [year1 , year2[ ]year1 , year2].

    Du coup, une fois cette formule trouvée, je me suis dit qu'on pouvait peut-être appliquer une formule similaire pour calculer le nombre d'années multiples de 4 et 400, je me suis alors pris la tête avec les nombres en base 4, 100 et 400 pour comprendre et vérifier qu'on pouvait le faire...


    Bon ben décidément, ce n'était vraiment pas aussi évident qu'on pourrait le croire au premier abord...
    Je me suis bien pris la tête...

  12. #12
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    (year2 // 100) - (year1 // 100) avec year1 = a1 - 1 et year2 = a2 - 1 c'est en fait le nombre exacte d'années multiples de 100 qu'il y a dans l'intervalle [year1 , year2[.
    C'est le nombre d'années multiples de 100 qu'il y a dans l'intervalle ]year1 , year2], donc celui de [a1, a2[.

    Bonne remarque. Du coup, étant donné les positions des parenthèses, le raisonnement qu'avait fait l'auteur du code relayé par ChatGPT était probablement :
    Nombre d'années bissextiles dans ]year1, year2] = nombre d'années multiples de 4 dans ]year1, year2] - nombre d'années multiples de 100 dans ]year1, year2] + nombre d'années multiples de 400 dans ]year1, year2] = ((year2 // 4) - (year1 // 4)) - ((year2 // 100) - (year1 // 100)) + ((year2 // 400) - (year1 // 400)).

    Un autre raisonnement possible dans lequel on tombe sur la même chose est :
    Nombre d'années bissextiles dans ]year1, year2] = nombre d'années bissextiles dans ]0, year2] - nombre d'années bissextiles dans ]0, year1] = ((year2 // 4) - (year2 // 100) + (year2 // 400)) - ((year1 // 4) - (year1 // 100) + (year1 // 400)).

    Quand j'avais vu les termes de l'expression renvoyée par ChatGPT, c'est le deuxième raisonnement qui m'est arrivé à l'esprit alors que le raisonnement de départ était sûrement le premier.

  13. #13
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Salut,

    Citation Envoyé par Pyramidev Voir le message
    C'est le nombre d'années multiples de 100 qu'il y a dans l'intervalle ]year1 , year2], donc celui de [a1, a2[.
    Ah oui, je me suis emmêlé les pinceaux avec l'intervalle, oui je voulais dire dans l'intervalle [a1, a2[, c'est bien cet intervalle que je voulais... J'ai corrigé mon message. Merci.

    Citation Envoyé par Pyramidev Voir le message
    Bonne remarque. Du coup, étant donné les positions des parenthèses, le raisonnement qu'avait fait l'auteur du code relayé par ChatGPT était probablement :
    Nombre d'années bissextiles dans ]year1, year2] = nombre d'années multiples de 4 dans ]year1, year2] - nombre d'années multiples de 100 dans ]year1, year2] + nombre d'années multiples de 400 dans ]year1, year2] = ((year2 // 4) - (year1 // 4)) - ((year2 // 100) - (year1 // 100)) + ((year2 // 400) - (year1 // 400)).
    Oui c'est bien comme cela que je l'ai compris... En fait cela vient de la définition d'une année bissextile (source):

    ...Les années sont en général bissextiles si elles sont multiples de quatre, toutefois elles ne le sont pas si elles sont multiples de cent à l'exception des années multiples de quatre cents qui sont elles bissextiles...
    ...

    Depuis l'ajustement du calendrier grégorien, l'année est bissextile (comportant 366 jours)1 seulement si elle respecte l’un des deux critères suivants :

    1. C1 : l'année est divisiblea par 4 sans être divisible par 100 (cas des années qui ne sont pas des multiples de 100) ;
    2. C2 : l'année est divisible par 400 (cas des années multiples de 100).


    Autrement dit : pour être bissextile, une année doit dans tous les cas être divisible par 4 ; mais si c’est une année de centenaire (comme 1800, 1900, etc.), elle doit en complément être divisible par 400.
    C'est d'ailleurs à partir de cette définition que j'ai écrit la fonction is_bissextile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def is_bissextile(annee):
        return annee % 4 == 0 and annee % 100 != 0 or annee % 400 == 0
    Et je pense aussi que la formule que j'avais trouvée vient de là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    diff = a2 - a1    
    nbr_annees_bissextiles = diff // 4 - diff // 100 + diff // 400
    Mais elle ne fonctionne pas toujours car les trois termes (diff // 4, diff // 100 et diff // 400) doivent dans certains cas être corrigés/compensés...

    En fait la partie diff // 4 - diff // 100 est censée traduire : "toutes les années multiple de 4 sauf celles qui sont multiples de 100".

    Mais comme parmi les années multiples de 100 il y en a qui sont bissextiles (ce sont celles qui sont multiples de 400) alors on ajoute diff // 400.

    Le principe est donc correcte mais comme on l'a vu la formule ne l'est pas toujours car encore une fois les trois termes ne donnent pas toujours correctement le nombre d'années multiples de 4, 100 et 400...

    Encore merci pour ta participation... Sujet résolu...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Dates] Nombre de jours ouvrés entre deux date
    Par meufeu dans le forum Langage
    Réponses: 1
    Dernier message: 31/01/2007, 17h50
  2. Nombre de jours ouvrables entre deux dates
    Par lenny_ dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 27/10/2006, 12h13
  3. Réponses: 1
    Dernier message: 10/08/2006, 14h43
  4. Compter le nombre de jours écoulés entre deux dates
    Par koKoTis dans le forum VBScript
    Réponses: 8
    Dernier message: 07/08/2006, 19h44
  5. Réponses: 7
    Dernier message: 03/02/2006, 13h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo