begin process at 2008 05 22 01:09:17
1 177 328 membres
14 nouveaux aujourd'hui
13 988 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 !

[UNIT] ROMANUTILS, TOUT POUR CONVERTIR LES CHIFFRES ROMAINS VERS LES ENTIERS ET INVERSEMENT


Information sur la source

Catégorie :Maths Classé sous : conversion, chiffre, arabes, romains Niveau : Débutant Date de création : 01/11/2005 Date de mise à jour : 03/11/2006 04:11:53 Vu / téléchargé: 9 118 / 364

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

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

Description

Aprés quelques heures de travail, voici le resultat final du tout premier algorythme que j'avais fait.

voici donc l'unitée RomanUtils qui permet de convertir les chiffres romain (strict) vers des entiers et inversement.

En esperant que tout cela vous serat utile et BONNE NOUVELLE pour une fois il y'a un Zip avec mon code!
Egalement dans le Zip, une petite application (RomanUtilsTest) pour montrer l'utilisation de l'unité RomanUtils,
avec en cadeaux, la Date du jours en chiffre romain! (hahaha ... pardon ...)


ps1 : voir le fichier .chm pour l'aide
ps2 : pas de commentaire dans la source pour le moment, a venir...

Conclusion

Pour toute questions, suggestions, amelioration, postez la sur ce sujet.

Possibilitée de mise a jours ... plus tard ...

Remerciements :
a Florenth pour ses bonne idées et ses suggestions de code.

FAFQ (Frequently Asked Funny Question):

- Avec quoi tu code ? avec Delphi 7 et mes doigts.
- Avec quoi tu fait les chm ? avec HTML Help Workshop de microsoft.
- Avec quoi tu fait tes zip ? avec l'excelent 7-Zip.
- Avec quoi on fait un Croc-Steak ? avec deux tranches de pain de mie, un bon gros steak haché et beaucoup de gruiyere. MIAM (j'ai faim!)
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

01 novembre 2005 10:09:50 :
petite erreur dans les StringReplaces, reparée... aprés une nuit blanche ... plus assé de neuronnes pour voir l'erreur. ^^
01 novembre 2005 10:31:41 :
ajout de 4 nouvelles valeurs qui permet de prendre en compte les notations "exotique" des chiffres romains. tel que IM pour 999 au lieu de CMXCIX par exemple.
05 novembre 2005 12:21:24 :
Grosse modification : refection totale de l'algorythme de RomanToInt, creation de plusieurs fonctions permettant de faire des traitements sur les chiffres Romain, mise en Unité du tout.
05 novembre 2005 12:27:31 :
correction d'une faute de "phrappe" ^^
05 novembre 2005 12:30:20 :
correction de la source affichée afin d'avoir une bonne colorisation syntaxique. (a quand une fonction "preview" sur delphifr !?)
05 novembre 2005 18:19:49 :
ajout d'un fichier d'aide au format CHM
05 novembre 2005 18:36:09 :
suppression de l'affichage de la source, inutile vus qu'il y a un zip ;)
07 novembre 2005 01:45:18 :
v0.0.1.2 : Amelioration des fonctions et du code, suppression d'apels redondant a certaines fonction interne, suppression de methodes lourdes pour un code plus condensé et leger.
07 novembre 2005 21:50:41 :
Amelioration des performances des fonctions RomanToInt, IntToRoman et RomanCharToValue. Merci a Florenth pour ses astuces.
03 novembre 2006 04:11:53 :
mise a jours v0.0.1.3 : augmentation des performances des routines pour l'anniversaire de la source.
  • signaler à un administrateur
    Commentaire de florenth le 01/11/2005 10:46:32

    En parlant des notation exotiques des chiffres romains,
    Est ce que IM est réellement accepté ? Normalament c'est CMXCIX comme tu l'as dit.
    Parce que si c'est accepté, alors il y a plusieurs façons d'écrire le même nombre (ce qui ne serait pas logique) et l'algoritme aurait alors des faiblesses

  • signaler à un administrateur
    Commentaire de Delphiprog le 01/11/2005 22:16:00 administrateur CS

    Une autre version réalisée par MHI est située à l'adresse : http://www.delphifr.com/code.aspx?ID=26944
    Ce qui est intéressant, c'est que chacun a sa manière de coder la solution.

  • signaler à un administrateur
    Commentaire de f0xi le 03/11/2005 13:53:25 administrateur CS

    @Florenth : tu mets le doigt dessus.

    a l'epoque des romains, les nombres etaient bien entendus normaliser et allant du plus grand au plus petit.

    la notation 999 s'ecrit bien CMXCIX et pas IM mais a notre epoque, certain transgresse les regles etablie et le note IM. pour etre plus court.
    certain meme quadruple les lettres ce qui n'etait pas le cas a l'epoque.
    donc comme il semble y avoir les vieux chiffres romain et les chiffres romain "moderne" j'ai prevus le coups dans ma fonction.

    mais aprés de nombreux tests, avec des valeurs "reglementaire" et "moderne" ma fonction ne semble pas commetre d'erreur. a chaque fois le resultat est bon.

    mais si tu decouvre une particularitée, fais le moi savoir.

    @delphiprog : aaaah! merci, justement j'avais chercher sans succés si il y avait deja quelque chose d'equivalent ici.
    mais voila justement le probleme que j'eradique dans ma fonction, cad, la notation moderne.
    la fonction de notre ami MHI est justement mise en echec par cette notation.
    de plus il semblerais que la fonction de MHI donne des resultat erroné, sur un exemple simple :
    XL (40) elle nous donne 60 (LX), idem pour XLVIII (48) elle renvoie 68...
    d'ailleur un petit coups d'oeuil a son algorythme et on remarque vite qu'il n'a pas pris en compte les soustractions. sans vouloir etre medisant vis a vis de son travail.
    je pense qu'il a oublier de faire quelques recherche preliminaire sur les chiffres romain et leur regles de base.

    son aglorythme est assé complexe (sans parler du fait qu'il est incomplet) comparer au miens.
    mais je preferais dire qu'ils ne sont pas comparable car j'utilise une methode carrement differente , il est vrai que je n'ai pas chercher midi a quatorze heure en me lançant dans des calculs et conditions complexe, aprés une nuit blanche on pardonneras mes neuronnes qui etaient deja fatigué par GLScene et sa hierarchie chaotique (je suis en train de me faire un Pong en openGL ... faut bien debuter par quelque chose).

  • signaler à un administrateur
    Commentaire de florenth le 03/11/2005 18:04:12

    C'est vrai que l'algorythme de MHI n'est pas tout à fait au point et qu'il est plus compliqué.
    La notation moderne: ça dépend comment tu l'entends. Si j'écris VL (non accepté en version originale), il faudait lire 45 alors que ta fonction affiche 55.

    Mais bon, c'est un peu tiré par les oreilles.

    Juste trois petites suggestions cependant:
    - Puisque tu ne modifie pas romstr (le parametre de la fonction), tu peux le déclarer constant (avec "const"). Il parait que ça optimise le code, surtout pour les chaines et les tableaux.

    - Au lieu d'utiliser res comme variable, utilise directement Result. Ce n'est pas comme en C++ où l'utilisaiton de "return" quitte la procédure.

    - Pourquoi ne pas prévoir une levée d'exception ou quelque chose comme cela si un des caractères n'est pas valide ?

  • signaler à un administrateur
    Commentaire de f0xi le 05/11/2005 01:21:32 administrateur CS

    @florenth :

    pour romstr, oui c'est effectivement vrai ...

    pour result, je crois que c'est une preference de ma part d'utiliser une locale plutotque result lui meme ayant deja eu des problemes avec l'utilisation directe de result dans d'autre appli.
    mais en effet ça pourrait aller avec elle.

    pour les caracteres non valide, c'est juste que j'ai pas eu le temps. ^^

    pour VL, en effet, c'est la ou justement tu avais raisons avec faiblesse de l'algo qui n'en est pas un au final.
    en fait on devrait tout bonnement supprimer la notation exotique de l'algo et appeler la fonction StrictRomanToInt();

    mais en meme temps, il faut se poser la question, ou trouve t'on encore des chiffres romain ?

    dans les numerotations des paragraphes de texte ... et c'est a peut prés tout.
    donc generalement n'utilise que I V et X...
    au dela, les gens passe sois au vrai chiffres 1,2,3 ou aux lettres A,B,C ...

    c'est pourquoi je n'ai pas chercher a ameliorer plus que ça la fonction.
    mais si tu te donne la peine de l'ameliorée, a la rigeur, je corrigerais en fonction de tes resultats (en te citant dans la source bien entendus).

    ps : en parlant de ça, a quand les codes sources commun ou on pourrais citer plusieurs personne en tant qu'auteur ?

  • signaler à un administrateur
    Commentaire de florenth le 05/11/2005 12:35:14

    Je vois que tu as mis à jour ta source qui maintenant permet de convertit dans les deux sens et sans un seul bug connu.

    Juste pour voir qu'il y a plusieurs façons de coder la même chose, je poste ici ma propre version de RomToInt() elle aussi sans bug connu.

    function RomainToInt(const Romain: string): Integer;
    var
      Pos: Integer;

      function ValeurLettre(const L: Char): Integer;
      begin
        case UpCase(L) of
          'I': Result := 1;
          'V': Result := 5;
          'X': Result := 10;
          'L': Result := 50;
          'C': Result := 100;
          'D': Result := 500;
          'M': Result := 1000;
        else
          raise Exception.CreateFmt('Caractère incorrect dans la chaîne (%s)', [L]);
        end; // case.
      end;

      procedure Ajout;
      var
        Val1, Val2: Integer;
      begin
        { Si on arrive pas à la fin de la chaîne. (il reste au moins un carac) }
        if Pos < Length(Romain) then
        begin
          { Récupération des deux valeurs. }
          Val1 := ValeurLettre(Romain[Pos]);
          Val2 := ValeurLettre(Romain[Pos + 1]);

          { Comparaison: test de soustraction. }
          if Val1 < Val2 then
          begin
            { Si oui, on ajoute la différence entre Val1 et Val2. }
            Inc(Result, Val2 - Val1);
            Inc(Pos);
          end
          else
          { Sinon, on ajoute juste Val1. }
            Inc(Result, Val1);
        end
        else
        begin
          { Si c'est le dernier caractère, juste l'ajouter. }
          Val1 := ValeurLettre(Romain[Pos]);
          Inc(Result, Val1);
        end;
      end;

    begin
      { Test de chaîne vide. }
      Result := 0;
      Assert(Romain <> '', 'La chaîne ne doit pas être vide.');

      { 1er carac: N° 1. }
      Pos := 1;

      { Tant que l'on arrive pas à la fin. }
      while Pos <= Length(Romain) do
      begin
        { On ajoute. }
        Ajout;
        { On passe au carac suivant. }
        Inc(Pos);
      end;
    end;

  • signaler à un administrateur
    Commentaire de f0xi le 05/11/2005 18:26:43 administrateur CS

    En effet, pas du tout la meme approche. par contre je sais pas si c'est les commentaires que tu as mis mais elle as l'air beaucoup plus "grosse"... ^^

    sinon j'ai mis a jours pas mal de chose derniere, j'ai notement ajouter un fichier d'aide pour l'utilisation de l'unité RomanUtils.

    je vais regarder a ta fonction de plus prés pour voir les difference entre les deux ...

  • signaler à un administrateur
    Commentaire de florenth le 05/11/2005 19:53:16

    Elle n'est pas plus longue que la tienne. Voire meme plus courte.
    Mais dans ton unité, tu as séparé les différentes méthodes que tu utilises dans tes différentes fonctions.
    Cela parait donc moins gros.

    Mais le truc, c'est que ma version est 13 fois plus rapide que la tienne ;-) et une version optimisée de ma version est jsqu'a 25 fois plus rapide ...

  • signaler à un administrateur
    Commentaire de f0xi le 06/11/2005 23:39:04 administrateur CS

    avec quoi verifie tu la vitesse des fonctions ?

    ça a l'air plutot enorme comme difference ...

  • signaler à un administrateur
    Commentaire de f0xi le 07/11/2005 01:30:57 administrateur CS

    bon alors, au vus de tes resultats, j'ai modifier la source de toute mes fonctions.
    voir l'historique et le nouveau zip.

  • signaler à un administrateur
    Commentaire de florenth le 07/11/2005 18:08:44

    Oula, on améliore les performances ...
    La concurence est rude.
    Je modifie ma fonction pour la rendre plus lisible (et plus rapide en même temps):

    function RomainToInt(const Romain: string): Integer;
    var
      Pos: Integer;

      function ValeurLettre(const L: Char): Integer;
      begin
        case UpCase(L) of
          'I': Result := 1;
          'V': Result := 5;
          'X': Result := 10;
          'L': Result := 50;
          'C': Result := 100;
          'D': Result := 500;
          'M': Result := 1000;
        else
          raise Exception.CreateFmt('Caractère incorrect dans la chaîne (%s)', [L]);
        end; // case.
      end;

      procedure Ajout;
      var
        Val1, Val2: Integer;
      begin
        { Récupération des deux valeurs. }
        Val1 := ValeurLettre(Romain[Pos]);
        Val2 := ValeurLettre(Romain[Pos + 1]);

        { Comparaison: test de soustraction. }
        if Val1 < Val2 then
        begin
          { Si oui, on ajoute la différence entre Val1 et Val2. }
          Inc(Result, Val2 - Val1);
          Inc(Pos);
        end
        else
        { Sinon, on ajoute juste Val1. }
          Inc(Result, Val1);
      end;

    begin
      { Test de chaîne vide. }
      Result := 0;
      Assert(Romain <> '', 'La chaîne ne doit pas être vide.');

      { 1er carac: N° 1. }
      Pos := 1;

      { Tant que l'on arrive pas à la fin. }
      while Pos < Length(Romain) do
      begin
        { On ajoute. }
        Ajout;
        { On passe au carac suivant. }
        Inc(Pos);
      end;
      Inc(Result, ValeurLettre(Romain[Pos])); // Le dernier carac.
    end;

    Résultats du test (cycles de 10000 executions): entre 470 et 520 ms pour ta fonction, entre 32 et 50 pour la mienne. Les chiffres sont les miens, ne te moques pas de mon ordi si tu obtiens moins.

    Pour faire les tests, j'ai fait cela: en mettant un bouton sur la fiche, et y colant le code de ma fonction, et en utilisant GetTickCount().

    procedure TForm1.Button3Click(Sender: TObject);
    var
      Tc, Tc1, Tc2, i: Cardinal;
    begin
      { Test de ta fonction. }
      Tc := GetTickCount;
      for i := 1 to 100000 do
        RomanUtils.RomanToInt('MMCDLXXXVII');
      Tc1 := GetTickCount - Tc;

      { Test de la mienne. }
      Tc := GetTickCount;
      for i := 1 to 100000 do
        RomainToInt('MMCDLXXXVII');
      Tc2 := GetTickCount - Tc;

      { Affichage des résultats. }
      ShowMessageFmt('RomanToInt() = %d ms - RomainToInt() = %d ms', [Tc1, Tc2]);
    end;

    Evidemment, les tests sont a effectuer au minimum une dizaine de fois, car l'utilisation du processeur par les autres programmes peuvent influencer la rapidité.

    @ ++ Florent

    PS: tu as drolement amélioré la vitesse de ta fonction. Si je me souvient bien des chiffres, j'obtenais environ 1000 ms pour 10000 executions (soit deux fois plus).

  • signaler à un administrateur
    Commentaire de florenth le 07/11/2005 18:10:03

    Excuse moi. Tu l'auras vu dans le code, les performances données sont vraies pour 100000 (cent mille) executions et non 10000 (dix mille) comme je l'avais dit

  • signaler à un administrateur
    Commentaire de f0xi le 07/11/2005 20:07:36 administrateur CS

    en effet, j'ai tester egalement de mon coté :

    Athlon 1800+ 1.53Ghz, DDR PC2100 2x133Mhz,
    Process load 22, CPU Charge 20-40% (firefox)

    RomanBench process mode : Real Time

    > 5 x 100 000 RomanToInt : moyenne 441ms
    (total 2203ms pour 500 000 requettes, plus rapide 437ms, plus longue 453ms)
    CPU Burn Charge : 58%
    VERDICT : reglo. on pourrait encore ameliorer ... Assembleur ? ^^

    > 5 x 100 000 IntToRoman : moyenne 213ms
    (total 1063ms pour 500 000 requettes, plus rapide 203ms, plus longue 219ms)
    CPU Burn Charge : 27%
    VERDICT : vraiment reglo.

    > 5 x 200 000 IsRomanNumber (str) : moyenne 22ms
    (total 109ms pour 1 000 000 requettes, plus rapide 15ms, plus longue 31ms)
    CPU Burn Charge : 8%
    VERDICT : carrement reglo.

    > 5 x 200 000 IsRomanNumber (int) : moyenne 0ms
    (total 0ms pour 1 000 000 requettes, plus rapide 0ms, plus longue 0ms)
    CPU Burn Charge : 0%
    VERDICT : no comment.

    j'avais jamais penser a tester comme ça ... les resultat parlent d'eux memes.

  • signaler à un administrateur
    Commentaire de f0xi le 07/11/2005 21:38:48 administrateur CS

    HAHA!

    bonne nouvelle aprés gros reflechissage :

    nouvelle données des benchs :

    > 5 x 100 000 RomanToInt : moyenne 56ms
    (total 282ms pour 500 000 requettes, plus rapide 47ms, plus longue 63ms)
    gain ~78%
    dont 22ms sont due a IsRomanNumber(STR), si on supprime la verification on descend donc a 34ms pour 100 000 requettes soit un gain de ~120%

    > 5 x 100 000 IntToRoman : moyenne 84ms
    (total 421ms pour 500 000 requettes, plus rapide 78ms, plus longue 94ms)
    gain ~25%

    ce qui donne des temps de moins d'une seconde pour traiter 1 millions de requettes.
    ce qui est largement raisonnable je pense.

    je mets donc a jours l'unitée en Version 1.2i (i pour improved) ^^

  • signaler à un administrateur
    Commentaire de JulioDelphi le 08/11/2006 15:06:35 administrateur CS

    HAPPY ANNIVERSAIRE LA SOURCE !!

  • signaler à un administrateur
    Commentaire de dje_jay le 30/10/2007 16:54:11

    Bon travail!

    Je l'ai d'ailleur porté en java : http://www.javafr.com/codes/VERSION-JAVA-ROMANUTILS-TOUT-CONVERTIR-CHIFFRES-ROMAINS-VERS_44548.aspx

    (J'ai tenu a respecter la source d'origine autant que possible)...

Ajouter un commentaire

Discussions en rapport avec ce code source

Appels d'offres

Pub



CalendriCode

Mai 2008
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS