begin process at 2008 08 22 00:37:41
1 229 731 membres
3 nouveaux aujourd'hui
14 267 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

BUG RANDOMRANGE


Information sur la source

Catégorie :Divers Classé sous : bug, math, random, range Niveau : Débutant Date de création : 04/12/2005 Vu / téléchargé: 2 895 / 117

Note :
9 / 10 - par 2 personnes
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (20)
Ajouter un commentaire et/ou une note

Description

Suite à l'étude du code proposé par florenth (http://www.delphifr.com/code.aspx?ID=34509) je me suis aperçu d'une erreur dans le code de la fonction RandomRange de l'unité Math.pas. En effet si l'on demande par exemple des nombres aléatoires de 3 à 8, la fonction renvoie des nombres de 3 à 7 !!

Voici le correctif à apporter.

Source

  • // ----- Code modifié ----- //
  • function RandomRange(const AFrom, ATo: Integer): Integer;
  • begin
  • if AFrom > ATo then
  • Result := Random(AFrom - ATo + 1 ) + ATo
  • else
  • Result := Random(ATo - AFrom + 1 ) + AFrom;
  • end;
// ----- Code modifié ----- //
function RandomRange(const AFrom, ATo: Integer): Integer;
begin
  if AFrom > ATo then
    Result := Random(AFrom - ATo + 1 ) + ATo
  else
    Result := Random(ATo - AFrom + 1 ) + AFrom;
end;

Conclusion

Quelques explications, sur la modification de la fonction originelle :

// ----- Code originel ----- //
function RandomRange(const AFrom, ATo: Integer): Integer;
begin
  if AFrom > ATo then
    Result := Random(AFrom - ATo) + ATo
  else
    Result := Random(ATo - AFrom) + AFrom;
end;

Supposons que Afrom=2 et ATo=3, dans ce cas, on aura Random(3-2)+2 soit Random(1)+2
0 <= Random(X)   < X
0 <= Random(1)   < 1
2 <= Random(1)+2 < 3, la fonction RandomRange ne renverra que des 2 !!!!

Supposons que Afrom=1 et ATo=5, dans ce cas, on aura Random(5-1)+1 soit Random(4)+1
0 <= Random(X)   < X
0 <= Random(4)   < 4
1 <= Random(4)+1 < 5, la fonction RandomRange renverra des nombres compris entre 1 et 4 !!!! et non 1 et 5

Pour utiliser le correctif, soit vous recompilez l'unité Math.pas en modifiant la source (pour ceux qu'ils l'ont), soit vous intégrez ce code dans une autre unité, par exemple CorrectifMath.pas (fichier joint)
L'appel de la fonction se fera en incluant l'unité dans la clause uses, puis en spécifiant au compilateur l'unité à utiliser :
  
  RandomRange(1,5); // Appel de la fonction originelle
  Math.RandomRange(1,5)); // Appel de la fonction originelle
  CorrectifMath.RandomRange(1,5)); // Appel de la fonction corrigée

Cordialement.
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

  • signaler à un administrateur
    Commentaire de cirec le 04/12/2005 19:45:58 administrateur CS

    Est ce que c'est vraiment une erreur où est ce que c'est normal ?

    En effet si l'on demande par exemple des nombres aléatoires de 3 à 8, la fonction renvoie des nombres de 3 à 7 !!

    Donc 8 - 3 = 5;

    3 4 5 6 7 8
    1 2 3 4 5

    Sachant cela RandomRange(3, 8) + 1 ca le fait
    et le "problème" est le même avec random puisque Random(10) donne un résultat de 0 à 9

    @+
    Cirec

  • signaler à un administrateur
    Commentaire de WhiteHippo le 04/12/2005 21:51:05

    Non Cirec, ce n'est pas normal !!

    La fonction Random renvoie un nombre aléatoire compris dans l'étendue 0 <=X <Range. Donc c'est clair, et précis. Là pas de problème, on parle d'étendue.

    Par contre, RandomRange "renvoie un entier choisi au hasard dans l'intervalle spécifié".
    Moi si je spécifie l'intervalle 3 à 8, RandomRange doit fournir un nombre compris entre 3 et 8 et non entre 3 et 7.

    Je serais d'accord avec toi si la fonction RandomRange, au même titre que la fonction Random, acceptait une étendue, et non un intervalle :
      function RandomRange [(Range:Integer)] ;

    N.B. RandomRange(3, 8) + 1 ne convient d'ailleurs pas car :
    RandomRange(3, 8) + 1 = Random(8 - 3) + 3 + 1 = Random(5) + 4
    0 <= Random(X) < X
    0 <= Random(5) < 5
    4 <= Random(5)+4 < 9

    Tandis que mon correctif te fournira bien TOUS les nombres de 3 à 8.

    Cordialement.

  • signaler à un administrateur
    Commentaire de f0xi le 05/12/2005 05:51:14 administrateur CS

    mmm bug ou pas bug ...

    il est vrai que quand on dit "dans l'interval specifié" sans preciser "avec max+1" on pourrait croire a une erreur, mais je dirais plutot une erreur de traduction de l'aide delphi.

    car il est quand meme bien precisé que randomrange fonctionne comme cela :

    min >= n < max

    il est vrai qu'en comparaison avec InRange par exemple, on devrait avoir RandomRange comme ça :
    min >= n <= max

    je ne pense pas que je corrigerais ce "defaut" dans l'unité math pour garder un max de compatibilitée avec tout ceux qui ne le ferons pas non plus.

    le mieux, plutot que de modifier la fonction serait d'ecrire RandomRange comme cela :

    X := RandomRange(min, max+1);

    pour se retrouver avec le bon interval, vus qu'il ne renverras jamais Max+1 comme valeur.

    un peu comme quand on ecrit : for x := 0 to listbox1.count-1 ... on ne modifie pas le composant listbox pour autant au niveau de count ou de l'indexation.

    Mais bon, je trouve moi meme cela pas trés logique au final...

  • signaler à un administrateur
    Commentaire de WhiteHippo le 05/12/2005 13:26:23

    Max+1, hummm pas d'accord non plus ;P

    Imaginons que l'on veuille l'ensemble des entiers 32 bits, c'est à dire de 0 à MaxInt, et bien le compilateur n'acceptera jamais RandomRange(0, maxInt+1);
    Tu auras alors une erreur du style "Débordement dans opération de conversion ou arithmétique".
    Donc au final, tu ne pourras pas avoir tous les nombres de 0..MaxInt.

    Cordialement.

  • signaler à un administrateur
    Commentaire de MAURICIO le 05/12/2005 17:39:56

    Voilà ce que dit le fichier d' aide:

    Description:

    RandomRange returns a random integer from the range that extends between AFrom and ATo (inclusive). RandomRange can handle negative ranges (where AFrom is greater than ATo).

    To initialize the random number generator, add a single call Randomize or assign a value to the RandSeed variable before making any calls to RandomRange.

    Alors buG ou mauvaise description ????

  • signaler à un administrateur
    Commentaire de cirec le 05/12/2005 17:46:56 administrateur CS

    En français pour ceux qui ont du mal avec l'anglais

    RandomRange renvoie un entier aléatoire appartenant à l'intervalle compris entre AFrom et ATo (bornes incluses). RandomRange peut utiliser des intervalles négatifs (où AFrom est supérieur à ATo).

    Pour initialiser le générateur de nombre aléatoire, ajoutez un seul appel Randomize ou affectez une valeur à la variable RandSeed avant d'effectuer un appel à RandomRange.

    Donc je dirais Bug

  • signaler à un administrateur
    Commentaire de MAURICIO le 05/12/2005 18:06:25

    Moi aussi étant donné que le mot Range est utilisé (ex. TTable.SetRange, ScrollBox1.Range etc ...) avec l' idée que les bornes soient incluses.
    Il faut donc rester cohérent si bien que cette source est largement justifiée et mérite au moins que l' on prenne note du problème.

  • signaler à un administrateur
    Commentaire de MAURICIO le 05/12/2005 18:15:51

    Je n' ai fait que résumer et conclure sur ce qu' à dit WhiteHippo. La description lui donnant raison ainsi que les autres utilisations du mot Range dans les propriétés ou fonctions de base à Delphi. Bug Bug et Bug !!!
    N' ayons pas peur des mots et consolons nous en nous disant que les autres langages comme le truc qui essaye de faire des programmes de chez MicroSoft en est bien plus rempli!!!

  • signaler à un administrateur
    Commentaire de cirec le 05/12/2005 18:25:00 administrateur CS

    tu voulais dire Microdaube non ? lol ^|^
                                          
    non il faut rester serieux je suis du même avis alors que au début je doutais fortement mais l'extrait de l'aide de Delphi est très claire "intervalle compris entre AFrom et ATo (bornes incluses)"

    Bon aller, bonne St Nicolas quand même ;-)
    @+
    Cirec

  • signaler à un administrateur
    Commentaire de f0xi le 05/12/2005 19:32:17 administrateur CS

    Oui en effet, completement d'accord avec vous quand a la justification de ce code source et plus aucun doute sur la traduction de l'aide.

    peut etre que les developpeurs delphi etait fatigués ce jours la est qu'ils ont un peu "merdé" mine de rien ^^

    mais quand meme, il est etonnant, si il s'agit bien d'un bug, qu'il n'est jamais ete reparré depuis Pascal 4.0, car je me souviens bien que Random fonctionné exactement pareil a l'epoque.
    idem pour randomrange.
    erreur voulue ?

    il est tout a fait logique, si je demande, choisis entre 1 et 10 que 1 et 10 soit egalement acceptable comme reponse.

    devrait on demander des reponses directement a borland sur cette erreur ?
    je dirais pourquoi pas et qui si colle ?
    http://www.borland.com/fr/company/contact/index.html

    pour ce qui est de mon exemple avec Max+1, c'etait bien entendus Max << a MaxInt (<< = carrement inferieur a)... surtout que je ne crois pas que randomrange accepte les int64.

    donc parfaitement d'accord sur l'erreur qui se produirais avec MaxInt+1...

    ou alors l'ecrire comme ça :

    x := randomrange(Min-1,MaxInt)+1;

    donc plus du tout question de Max+1 mais plutot (Min-1,Max)+1 ...
    Mais la erreur plosible due a MinInt-1 ... encore une fois depassement de l'interval des integer.

    cette fois plus de doute, RandomRange a un bug ... un gros meme.

    mais je ne modifierais pas directement RandomRange, je vais plutot créer une fonction identique  mais non bugée dans mon unité d'outils... encore une fois, dans le soucis de rester compatible avec mes anciens programmes et egalement ceux des autres.

    en tout cas, je mets quand meme une bonne note pour avoir soulever ce probleme qui est parfaitement justifié.

  • signaler à un administrateur
    Commentaire de WhiteHippo le 05/12/2005 23:15:36

    Après quelques recherches, il apparait que le problème était connu (http://qc.borland.com/wc/qcmain.aspx?d=3541)
    et que le bug soit corrigé pour Delphi 2005 (Build 9.0.1761.24408).
    N'ayant pas cette version (Je developpe en Delphi 7 pro) je ne peux le vérifier.

    Par contre, je me demande si ils ont choisis de corriger la documentation (en précisant que c'est un intervalle exclusif) ou bien le code ???

    Allez, soyons médisant !! la documentation ;P

    N.B. Si tel était le cas, alors il persiste un réel problème avec ce code.

    Cordialement.

  • signaler à un administrateur
    Commentaire de cirec le 05/12/2005 23:25:54 administrateur CS

    C'est pire que ça il n'y a rien de corrigé dans cette version du moins (Build 9.0.1761.24408). !!!

    peut être pour la suivante ?

    @+
    Cirec

  • signaler à un administrateur
    Commentaire de MAURICIO le 06/12/2005 10:13:40

    Bon, y a pas mort d' homme non plus.
    Je pense que cela est peut-être voulu (portage du Pascal donc) et que cette erreur viendrait d' une volonté de compatibilité.

    J' aurai préféré une mise à jour de la fonction. Peut-être en modifiant son nom pour que dans une future version il y ait une erreur de compil'. A+

  • signaler à un administrateur
    Commentaire de cirec le 06/12/2005 10:22:32 administrateur CS

    Ok mais l'article de Borland est claire à ce sujet
    Resolved in Build : 9.0.1761.24408 ?

    @+
    Cirec

  • signaler à un administrateur
    Commentaire de f0xi le 06/12/2005 19:20:34 administrateur CS

    j'ai verifier egalement de mon coté, Random etait exactement pareil sur TP7.
    RandomRange n'existe apparement que depuis Delphi 2.0 (verifier sur la reference D2)
    et bien entendus elle fonctionne comme cela deja.

    Peut etre voir egalement comment fonctionne RandomRange dans c++

    plus inquietant, c'est qu'ils disent "corrigé dans la version 2005" et qu'apparement ... pas.

    bon ben moi en tout cas j'ai implementé la nouvelle fonction sous le nom de RandRange.

  • signaler à un administrateur
    Commentaire de WhiteHippo le 06/12/2005 19:28:51

    Moi Mauricio, ce qui me chagrine, ce le fait de persister dans une voie toute en sachant qu'elle est erronée. Une volonté de comptabilité, soit mais le problème c'est que de nombreuses sources qui utilisent cette fonction, ne fonctionne certainement pas correctement.
    Un autre exemple d'utilisation buggée :

    type
      TMonChoix = ( mcCeci, mcCela, mcOuCeci, mcOuCela, mcOuEncoreCeci, mcOuEncoreCela ) ;

    Un appel de TMonChoix( randomrange( Low(TMonChoix), High(TMonChoix) ) ) ne fournira jamais mcOuEncoreCela.

    Volonté de compatibilité soit mais alors volonté de compatibilité des bugs !!! ;P
                
    Quand à la modification du nom, pas vraiment, enfin pas tout à fait. Je verrais plutot une modification du code pour cette fonction, plus une nouvelle fonction RandomRangeExclusive qui reprendrait l'ancien code. Cela serait, je pense, beaucoup plus cohérent.

    N.B. Je ne pense pas que la modification de ce code entraine de grandes modifications, mais il permettra simplement à ses utilisateurs d'avoir TOUTES les valeurs normallement prévues!!

    Cordialement.

  • signaler à un administrateur
    Commentaire de cirec le 06/12/2005 23:20:04 administrateur CS


    Effectivement cette version là est buggée (tu compiles même pas) ^_^:
    randomrange( Low(TMonChoix), High(TMonChoix) )

    Je pense que celle-ci fonctionnera un peut mieux: randomrange( Integer(Low(TMonChoix)),
      Integer(High(TMonChoix)) );

    sans pour autant donner le bon résultat il manquera toujours  "mcOuEncoreCela" je vous l'accorde.

    @+
    Cirec

  • signaler à un administrateur
    Commentaire de cirec le 06/12/2005 23:26:53 administrateur CS

    Ps: je met une note de dix non pas parce que le code est extraordinaire non mais parce que ça fait longtemps que j’avais remarqué cela... mais bon j'ai trouvé ça normal et j'ai pas cherché plus loin. #^_^#

    @+
    Cirec

  • signaler à un administrateur
    Commentaire de WhiteHippo le 07/12/2005 00:06:05

    Merci Cirec pour la note et pour avoir corriger ma grossière erreur (Oups !!) C'est ça de vouloir poster trop rapidement. Pourtant j'avais bien relu, 2 fois au moins comme le précise la nétiquette, mais pour les fautes d'orthographes pas pour celle du code (fait au feeling j'avoue) ;D

    Cordialement.

  • signaler à un administrateur
    Commentaire de cirec le 07/12/2005 00:14:31 administrateur CS

    You welcome

    ça nous arrive a tous et si c'est pas le cas ça arrivera

    @+
    Cirec

Ajouter un commentaire

Discussions en rapport avec ce code source

Pub



Appels d'offres

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

Téléchargements

Boutique

Boutique de goodies CodeS-SourceS