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

Algorithmes et structures de données Discussion :

Arrondi au multiple le plus proche ...


Sujet :

Algorithmes et structures de données

  1. #1
    Membre habitué Avatar de Marco85
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 210
    Points : 187
    Points
    187
    Par défaut Arrondi au multiple le plus proche ...
    Bonjour,

    J'ai un nombre X (par exemple 1004) et un nombre Y (par exemple 500). Je souhaiterais trouver un algorithme me permettant d'arrondir X au multiple le plus proche de Y (dans ce cas 1000).

    Auriez-vous des pistes vers lesquelles chercher ?

    Merci d'avance,

    Marco85
    If you cannot explain a concept to a six year-old, then you do not fully understand it. [Albert Einstein]

  2. #2
    Expert éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    Par défaut
    Je te propose quelque chose comme ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    différencePrécédente = y - x
    i = 2
    tant que l'on a pas trouvé : 
         différenceSuivante = (y*i) - x
         si différenceSuivante n'est pas plus petit que différencePrécédente
              alors besti = i - 1
              on termine la boucle
         sinon
              différencePrécédente = différenceSuivante
              on incrémente i et on recommence une fois la boucle
    fin de la boucle
    newx = y * besti

  3. #3
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    J'ai loupé quelque chose? Parce qu'il me semble qu'on n'a pas besoin d'une boucle, en utilisant la division entière,

    floor = (X/Y) * Y;
    ceil = floor + Y;

    if( X-floor< ceil-X)
    return floor;
    else
    return ceil;
    Cela me semble plus simple,
    Jc

  4. #4
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    y*floor((x+y/2)/y)
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #5
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    y*floor((x+y/2)/y)
    Exact, sauf que si on utilise un langage acceptant la division entière (et que nos arguments soient entiers!) cela peut donc se simplifier en cela:

    y * ((x+y/2)/y)

  6. #6
    Membre habitué Avatar de Marco85
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 210
    Points : 187
    Points
    187
    Par défaut
    Citation Envoyé par fearyourself
    Merci beaucoup !!! Cette solution me plaît énormément !!!

    Merci encore,

    Marco85
    If you cannot explain a concept to a six year-old, then you do not fully understand it. [Albert Einstein]

  7. #7
    Expert éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    Par défaut
    ohlalala, je me suis complétement loosé

    mais j'ai pas du tout comprendre le problème...

  8. #8
    Membre expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Points : 3 166
    Points
    3 166
    Par défaut
    Si je peux me permettre, on peut envisager ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    y * ((x + ((x/abs(x)) * y) / 2) / y)
    Cela aura l'avantage de trouver le multiple le plus proche aussi pour les entiers négatifs. C'est l'objectif du facteur (x/abs(x)) appliqué à y/2 ...
    La FAQ Perl est par ici
    : La fonction "Rechercher", on aurait dû la nommer "Retrouver" - essayez et vous verrez pourquoi !

  9. #9
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    On pourrait aussi ajouter le problème du y négatif ou non...

    Le seul cas qui pose problème est justement lorsque x est négatif...

    -1024 -500 rendrait :

    -500 * (( -1024 + 250) / -500) = -500 * (-774/500) = -500
    Pour le résoudre, il faurait donc faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    y * ((x + ((x/abs(x)) * (y/abs(y)) * y) / 2) / y)
    Ce qui donnerait:
    -500 * (( -1024 - 250) / -500) = -500 * (-1274/-500) = -1000
    Jc

  10. #10
    Membre actif Avatar de SaintAmand
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 174
    Points : 203
    Points
    203
    Par défaut
    Marco85 est peut-être satisfait, mais moi à sa place je ne le serais pas :-) et ce pour les raisons suivantes.
    1) Vos formules sont très compliquées, et en tout cas peu efficaces (4 divisions et 3 multiplications !!!!) et passent sous silence les difficultés. Un bon point pour fearyourself dont la première réponse est presque parfaite. Cela dit j'ai là une idée de problème. A mon prochain devoir, je donnerais l'une de vos formules et il faudra deviner ce qu'elle calcule.
    2) Vous ne précisez pas quelle convention vous utilisez pour vos divisions entières. En effet, le théorème de la division euclidienne dans ZxZ* dit que pour tous entiers (a,b) de ZxZ*, il existe au moins un couple (q,r) de ZxZ tel que a = bq + r et |r| < |b|.
    Il faudrait donc préciser quelle condition vous imposez à r pour avoir l'unicité. En général 0 <= r < b ou -b/2 < r <= b/2.
    Suivant les langages, et même pour un même langage (par ex. le C), suivant les implémentations on pourra avoir des variations à se sujet.

    Moi ce que je propose c'est de partir de la 1ère idée de fearyourself. Pour avoir un résultat indépendant du choix de la convention pour la division euclidienne, je considérerais la division dans R et [x] désignera la partie entière (le plus grand entier inférieur ou égal à x).
    Dans ce cas m = [x/y] * y est le plus grand multiple de y inférieur ou égal à x et n = m + y est le plus petit multiple de x supérieur ou égal à x. Il suffit maintenant de considérer les distances de x à m et n soit x - m et n - x. Enfin que fait-on si x est équidistant de m et n? Il faut définir une convention. Au final on s'en tire avec une division, un produit et une comparaison.

    --
    SaintAmand

  11. #11
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par SaintAmand
    2) Vous ne précisez pas quelle convention vous utilisez pour vos divisions entières. En effet, le théorème de la division euclidienne dans ZxZ* dit que pour tous entiers (a,b) de ZxZ*, il existe au moins un couple (q,r) de ZxZ tel que a = bq + r et |r| < |b|.
    Il faudrait donc préciser quelle condition vous imposez à r pour avoir l'unicité. En général 0 <= r < b ou -b/2 < r <= b/2.
    Suivant les langages, et même pour un même langage (par ex. le C), suivant les implémentations on pourra avoir des variations à se sujet.
    En C, l'unicité résulte de |bq| <= |a| ce qui revient à dire que le signe de r, si r est non nul, est le signe de a. C'est aussi ce qui est demandé par Fortran et Ada (Ada a deux opérateurs pour le reste, mais un pour la division) et je ne connais pas de processeur ayant une instruction de division ne le faisant pas a part MMIX.

    Je n'ai jamais vu -b/2 < r <= b/2 utilisé directement pas un processeur ou un langage. La contrainte que Knuth utilise pour MMIX, a aussi été proposée par Chinal, est l'autre opérateur de reste d'Ada, c'est signe de r est le signe de b pour r non nul.

    Moi ce que je propose c'est de partir de la 1ère idée de fearyourself. Pour avoir un résultat indépendant du choix de la convention pour la division euclidienne, je considérerais la division dans R et [x] désignera la partie entière (le plus grand entier inférieur ou égal à x).
    Dans ce cas m = [x/y] * y est le plus grand multiple de y inférieur ou égal à x et n = m + y est le plus petit multiple de x supérieur ou égal à x. Il suffit maintenant de considérer les distances de x à m et n soit x - m et n - x. Enfin que fait-on si x est équidistant de m et n? Il faut définir une convention. Au final on s'en tire avec une division, un produit et une comparaison.
    Contre exemple x = -10 et y = -6

    En passantest un moyen bien compliqué de dire
    A+
    --
    Jean-Marc
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #12
    Membre actif Avatar de SaintAmand
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 174
    Points : 203
    Points
    203
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Citation Envoyé par SaintAmand
    Moi ce que je propose c'est de partir de la 1ère idée de fearyourself. Pour avoir un résultat indépendant du choix de la convention pour la division euclidienne, je considérerais la division dans R et [x] désignera la partie entière (le plus grand entier inférieur ou égal à x).
    Dans ce cas m = [x/y] * y est le plus grand multiple de y inférieur ou égal à x et n = m + y est le plus petit multiple de x supérieur ou égal à x. Il suffit maintenant de considérer les distances de x à m et n soit x - m et n - x. Enfin que fait-on si x est équidistant de m et n? Il faut définir une convention. Au final on s'en tire avec une division, un produit et une comparaison.
    Contre exemple x = -10 et y = -6
    Oups, désolé. J'ai pensé (mais j'ai oublié de l'écrire) que l'on pouvait se ramener au cas ou y est positif (l'ens. des multiples de y est le même que l'ens. des multiples de -y). En effet, si y<0 alors m est le plus petit multiple de y plus grand ou egal à x et n le plus grand multiple de y plus petit ou égal à y. Il faut donc penser à écrire les distances avec les valeurs absolues (|m-x| et |n-y|) si l'on ne remplace pas y par |y|.

    --
    SaintAmand

  13. #13
    Membre actif Avatar de SaintAmand
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 174
    Points : 203
    Points
    203
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    En C, l'unicité résulte de |bq| <= |a| ce qui revient à dire que le signe de r, si r est non nul, est le signe de a.
    Ceci est valable pour la norme C99. Sinon dans le Kernighan & Ritchie, je cite: "The direction of truncature for / and the sign of the result for % are machine-dependent for negative operands...".

    --
    SaintAmand

  14. #14
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par SaintAmand
    Citation Envoyé par Jean-Marc.Bourguet
    En C, l'unicité résulte de |bq| <= |a| ce qui revient à dire que le signe de r, si r est non nul, est le signe de a.
    Ceci est valable pour la norme C99. Sinon dans le Kernighan & Ritchie, je cite: "The direction of truncature for / and the sign of the result for % are machine-dependent for negative operands...".
    Je sais. J'aimerais confirmation que la latitude laissé par K&R (qui se retrouve dans C90) a été utilisée. Ou même, simplement confirmation de l'existance d'une machine avec une division cablée qui ne suit pas cette règle. J'ai rencontré l'affirmation que ça existe, mais n'ai jamais trouvé le nom d'une telle machine, même pas chez Blaaw et Brooks (Computer Architecture, concepts and evolution) où l'on trouve pas mal de bêtes étranges.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  15. #15
    Nouveau Candidat au Club
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Juillet 2009
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2009
    Messages : 1
    Points : 1
    Points
    1
    Par défaut définir son multiple exemple 500
    bjr , une solution en php

    1. function multipleNombre ($val,$mul) {
    2. $a = ((float)$val)/((float)$mul);
    3. $b = intval($a);
    4. if(($a-$b)<=0.5){
    5. $r = $b*$mul;
    6. }else{
    7. $r = ($b+1)*$mul;
    8. }
    9. $r = max($r,$mul);
    10. return $r;
    11. }

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

Discussions similaires

  1. IEEE 754 soustraction et arrondi au plus proche puis nombre pair
    Par Iradrille dans le forum Mathématiques
    Réponses: 0
    Dernier message: 17/05/2014, 08h35
  2. [javascool]Multiple de 10 le plus proche
    Par alleztulle dans le forum Autres
    Réponses: 9
    Dernier message: 28/01/2013, 21h44
  3. Arrondi au nombre entier le plus proche
    Par heliy dans le forum SAP
    Réponses: 4
    Dernier message: 21/04/2011, 08h44
  4. Arrondi à 1 ou 5 x 10^m le plus proche ?
    Par tnarol dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 29/09/2006, 17h32
  5. Récupurer via une requête SQL la valeur la plus proche
    Par yoda_style dans le forum Langage SQL
    Réponses: 9
    Dernier message: 27/04/2004, 13h52

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