Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1337 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  Parser un long sur une base de 36

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Parser un long sur une base de 36

n°1766448
creusois
Posté le 29-07-2008 à 17:03:32  profilanswer
 

Bonjour,
 
J'ai un petit souci dans la refonte d'une petite appli J2SE en C#. Le programme utilise la fonction :
 

Code :
  1. Long.parseLong(new String(tmp), 36)


 
tmp etant un tableau de byte (byte[])
 
Apparament le 36 est la base sur lequel il faut s'appuyer.  
 
Etant donnée qu'il ne sagit pas d'une base courante, je ne sais pas comment faire de même en C#.
 
Si qqn à la solution, merci.

mood
Publicité
Posté le 29-07-2008 à 17:03:32  profilanswer
 

n°1766695
MagicBuzz
Posté le 30-07-2008 à 12:56:17  profilanswer
 

c'est à dire ? chaque byte de ton tmp va de 0 à 35, c'est ça ?
 
et si t'as par exemple :
 
24 14
 
tu veux avoir 24*36 + 14 = 878 ?
 
ils sont triés dans quel ordre tes bytes dans tmp ?
 
genre c'est un byte[n] et les valeurs sont remplies par la fin en remontant vers 0, l'index n-1 étant l'unité ?
ou si c'est l'inverse ? (index 0 = unité, index 1 = dizaine, etc.)
 
dans tous les cas, pour moi t'es bon pour faire une méthode à la main qui gère le truc, parceque tu bosses pas à proprement en base 36 (base 36 ce sera plutôt une représentation string au format 0-9a-z à mon avis)
 
ou alors ton tmp contient les valeurs ASCII des caractères 0-9a-z ? (et dans ce cas, effectivement tu bosses bien en base 36 au niveau de ton string), mais rien que le string(byte[]) ça ne marchera pas. en C#, byte et char ne sont pas synonymes et n'ont rien à voir.
 
à priori, va falloir faire un truc à la mano.


Message édité par MagicBuzz le 30-07-2008 à 13:00:33
n°1766710
masklinn
í dag viðrar vel til loftárása
Posté le 30-07-2008 à 13:35:20  profilanswer
 

creusois a écrit :

Bonjour,

 

J'ai un petit souci dans la refonte d'une petite appli J2SE en C#. Le programme utilise la fonction :

 
Code :
  1. Long.parseLong(new String(tmp), 36)
 

tmp etant un tableau de byte (byte[])

 

Apparament le 36 est la base sur lequel il faut s'appuyer.

 

Etant donnée qu'il ne sagit pas d'une base courante, je ne sais pas comment faire de même en C#.

 

Si qqn à la solution, merci.


Tu as Convert.ToInt32(String, IFormatProvider) et Convert.ToString(Int32, IFormatProvider), mais MS n'a apparement jugé bon ni de supporter des bases arbitraire (Convert.ToInt32(String, Int32) et Convert.ToString(Int32, Int32) ne gèrent que les bases 2, 8, 10, et 16) ni d'inclure un IFormatProvider permettant de récupérer un format pour une base arbitraire (pour autant que je puisse le voir en tout cas).

 

Essaies de chercher sur google si tu en trouves un fait par quelqu'un d'autre.


Message édité par masklinn le 30-07-2008 à 13:35:50

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1766721
MagicBuzz
Posté le 30-07-2008 à 14:03:50  profilanswer
 

Je viens de coder ça, ça m'a l'air de marcher...
 

Code :
  1. using System;
  2. using SandBoxConsole.Base36;
  3. namespace SandBoxConsole
  4. {
  5.    class Program
  6.    {
  7.        static void Main(string[] args)
  8.        {
  9.            string s = "1a";
  10.            Console.WriteLine(s);
  11.            Number n = (Number)s;
  12.            Console.WriteLine((long)n);
  13.            Console.WriteLine((string)n);
  14.            long l = (long)n;
  15.            Console.WriteLine(l);
  16.            Console.WriteLine((string)((Number)l));
  17.            Console.ReadKey(true);
  18.        }
  19.    }
  20.    namespace Base36
  21.    {
  22.        class Digit
  23.        {
  24.            public const string EnumDigits = "0123456789abcdefghijklmnopqrstuvwxyz";
  25.            private char digit;
  26.            public Digit(int d)
  27.            {
  28.                char tmp;
  29.                if (char.TryParse(char.ConvertFromUtf32(d).ToLower(), out tmp))
  30.                {
  31.                    if (tmp >= '0' && tmp <= '9' || tmp >= 'a' && tmp <= 'z')
  32.                    {
  33.                        digit = tmp;
  34.                        return;
  35.                    }
  36.                }
  37.                throw new OverflowException(string.Format("Le code UTF32 '{0}' n'est pas un caractère reconnu en base 36.", d));  
  38.            }
  39.            public Digit(char d)
  40.            {
  41.                d = char.ToLower(d);
  42.                if (d >= '0' && d <= '9' || d >= 'a' && d <= 'z')
  43.                {
  44.                    digit = d;
  45.                    return;
  46.                }
  47.                throw new OverflowException(string.Format("Le caractère '{0}' n'est pas un caractère reconnu en base 36.", d));  
  48.            }
  49.            public char ToChar()
  50.            {
  51.                return digit;
  52.            }
  53.            public long ToLong()
  54.            {
  55.                return EnumDigits.IndexOf(digit);
  56.            }
  57.            public static explicit operator char(Digit value)
  58.            {
  59.                return value.ToChar();
  60.            }
  61.            public static explicit operator long(Digit value)
  62.            {
  63.                return value.ToLong();
  64.            }
  65.            public static explicit operator Digit(char value)
  66.            {
  67.                return new Digit(value);
  68.            }
  69.            public static explicit operator Digit(int value)
  70.            {
  71.                return new Digit(value);
  72.            }
  73.        }
  74.        class Number
  75.        {
  76.            private Digit[] digits;
  77.            public Number(long n)
  78.            {
  79.                
  80.                digits = new Digit[(int)Math.Ceiling(Math.Log(n, 36))];
  81.                int i = 0;
  82.                while (n > 0)
  83.                {
  84.                    digits[i++] = (Digit)Digit.EnumDigits[(int)(n % 36)];
  85.                    n /= 36;
  86.                }
  87.            }
  88.            public Number(string s)
  89.            {
  90.                digits = new Digit[s.Length];
  91.                for (int i = 0, cpt = s.Length - 1; i <= cpt; i++)
  92.                {
  93.                    digits[i] = new Digit(s[cpt - i]);
  94.                }
  95.            }
  96.            public long ToLong()
  97.            {
  98.                long n = 0;
  99.                long mul = 1;
  100.                for (int i = 0, cpt = digits.Length; i < cpt; i++)
  101.                {
  102.                    n += (long)digits[i] * mul;
  103.                    mul *= 36;
  104.                }
  105.                return n;
  106.            }
  107.            public override string ToString()
  108.            {
  109.                string s = string.Empty;
  110.                for (int i = digits.Length - 1; i >= 0; i--)
  111.                {
  112.                    s += (char)digits[i];
  113.                }
  114.                return s;
  115.            }
  116.            public static explicit operator Number(long value)
  117.            {
  118.                return new Number(value);
  119.            }
  120.            public static explicit operator Number(string value)
  121.            {
  122.                return new Number(value);
  123.            }
  124.            public static explicit operator long(Number value)
  125.            {
  126.                return value.ToLong();
  127.            }
  128.            public static explicit operator string(Number value)
  129.            {
  130.                return value.ToString();
  131.            }
  132.        }
  133.    }
  134. }


 


1a
46
1a
46
1a


Message édité par MagicBuzz le 30-07-2008 à 14:11:47
n°1766727
MagicBuzz
Posté le 30-07-2008 à 14:07:29  profilanswer
 

(sauf qu'en fait, ça calcule pas bien, je vérifie j'ai une couille quelque part :D)

n°1766729
masklinn
í dag viðrar vel til loftárása
Posté le 30-07-2008 à 14:10:24  profilanswer
 

[:prozac]  
 
http://www.codeproject.com/KB/reci [...] erter.aspx


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1766730
MagicBuzz
Posté le 30-07-2008 à 14:11:54  profilanswer
 

Voilà, c'est corrigé ;)

n°1766732
MagicBuzz
Posté le 30-07-2008 à 14:13:07  profilanswer
 

Ouais ben mon truc il marche bien et c'est pas du repompage d'un site :o
 
Et à l'utilisation, tu gardes ta valeur dans ta base, tu passes pas par des strings à tout bout de champ :spamafote:

Message cité 1 fois
Message édité par MagicBuzz le 30-07-2008 à 14:14:13
n°1766737
masklinn
í dag viðrar vel til loftárása
Posté le 30-07-2008 à 14:19:46  profilanswer
 

MagicBuzz a écrit :

Ouais ben mon truc il marche bien


Oui oui [:pingouino]

MagicBuzz a écrit :

et c'est pas du repompage d'un site :o


C'est pas du repompage, c'est l'utilisation de l'effort des autres mis à dispo du public (ce qui est le rôle de codeproject). En d'autres termes, c'est être intelligent. Sans compter que le truc codeproject effectue la conversion entre des bases totalement arbitraires.

MagicBuzz a écrit :

Et à l'utilisation, tu gardes ta valeur dans ta base, tu passes pas par des strings à tout bout de champ :spamafote:


Il y a aussi des classes de bases plus ou moins arbitraires sur codeproj, mais c'est clairement pas ce que demande creusois [:spamafote]


Message édité par masklinn le 30-07-2008 à 15:11:13

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°1766745
MagicBuzz
Posté le 30-07-2008 à 14:26:47  profilanswer
 

il veut convertir un array de char en long en respectant la base 36, ce que fait mon code.
 
celui de code projet permet de convertir une string en string en changeant la baseutilisée pour représentation, ce qui ne correspond pas à ce qu'il veut
 
(non mais :o)

mood
Publicité
Posté le 30-07-2008 à 14:26:47  profilanswer
 

n°1766765
creusois
Posté le 30-07-2008 à 15:33:44  profilanswer
 

MagicBuzz a écrit :

il veut convertir un array de char en long en respectant la base 36, ce que fait mon code.
 
celui de code projet permet de convertir une string en string en changeant la baseutilisée pour représentation, ce qui ne correspond pas à ce qu'il veut
 
(non mais :o)


 
Je vois que mon post dechaine les passions. J'ai réussi à faire ce que je voulais ne le codant à la mano, mais je pense que j'ai pas fait la meilleur méthode (surtout dans les toString() et les parse par dessus. J'ai un peu de mal dans les conversion de byte en char.
 
Voici ma fonction
 

Code :
  1. public long parseBase(char[] str)
  2.         {
  3.             Dictionary<char,int> tabCorrespondance = new Dictionary<char,int>();
  4.             tabCorrespondance.Add('0', 0);
  5.             tabCorrespondance.Add('1', 1);
  6.             tabCorrespondance.Add('2', 2);
  7.             tabCorrespondance.Add('3', 3);
  8.             tabCorrespondance.Add('4', 4);
  9.             tabCorrespondance.Add('5', 5);
  10.             tabCorrespondance.Add('6', 6);
  11.             tabCorrespondance.Add('7', 7);
  12.             tabCorrespondance.Add('8', 8);
  13.             tabCorrespondance.Add('9', 9);
  14.             tabCorrespondance.Add('a', 10);
  15.             tabCorrespondance.Add('b', 11);
  16.             tabCorrespondance.Add('c', 12);
  17.             tabCorrespondance.Add('d', 13);
  18.             tabCorrespondance.Add('e', 14);
  19.             tabCorrespondance.Add('f', 15);
  20.             tabCorrespondance.Add('g', 16);
  21.             tabCorrespondance.Add('h', 17);
  22.             tabCorrespondance.Add('i', 18);
  23.             tabCorrespondance.Add('j', 19);
  24.             tabCorrespondance.Add('k', 20);
  25.             tabCorrespondance.Add('l', 21);
  26.             tabCorrespondance.Add('m', 22);
  27.             tabCorrespondance.Add('n', 23);
  28.             tabCorrespondance.Add('o', 24);
  29.             tabCorrespondance.Add('p', 25);
  30.             tabCorrespondance.Add('q', 26);
  31.             tabCorrespondance.Add('r', 27);
  32.             tabCorrespondance.Add('s', 28);
  33.             tabCorrespondance.Add('t', 29);
  34.             tabCorrespondance.Add('u', 30);
  35.             tabCorrespondance.Add('v', 31);
  36.             tabCorrespondance.Add('w', 32);
  37.             tabCorrespondance.Add('x', 33);
  38.             tabCorrespondance.Add('y', 34);
  39.             tabCorrespondance.Add('z', 35);
  40.             Array.Reverse(str);
  41.             long nb = 0;
  42.             double scale = 0;
  43.             foreach (char var in str)
  44.             {
  45.                 if (scale == 0)
  46.                 {
  47.                     nb += tabCorrespondance[var];
  48.                 }
  49.                 else
  50.                 {
  51.                     nb += long.Parse(Math.Pow(double.Parse("36" ), scale).ToString()) * tabCorrespondance[var];
  52.                 }
  53.                 scale++;
  54.             }
  55.             return nb;
  56. }

n°1768639
TotalRecal​l
Posté le 03-08-2008 à 20:46:25  profilanswer
 

creusois a écrit :

 
Code :
  1. {                 
  2.                     nb += long.Parse(Math.Pow(double.Parse("36" ), scale).ToString()) * tabCorrespondance[var];
  3.                 }



[:pingouino]


Message édité par TotalRecall le 03-08-2008 à 20:46:46

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°1768696
MagicBuzz
Posté le 04-08-2008 à 00:33:52  profilanswer
 

c vrai que j'avais pas fait gaffe à sa façon de faire des cast explicits :D

n°1768697
MagicBuzz
Posté le 04-08-2008 à 00:49:53  profilanswer
 

Sinon, pour info aussi, même si c'est plus de la bidouille sauce C que de l'algo "propre", le coup du dictionnaire qui fait 36 lignes et doit bouffer au bas mot 1 Ko de mémoire inutilement se gère très bien de cette façon old school :
 

Code :
  1. public const string EnumDigits = "0123456789abcdefghijklmnopqrstuvwxyz";


 
puis à l'utilisation :

Code :
  1. char ChiffreBase36 = EnumDigits[ValeurEntiere];
  2. int ValeurEntiere = EnumDigits.indexOf(ChiffreBase36);


 
L'astuce, c'est qu'une chaîne de caractères, c'est ni plus ni moins qu'un tableau de char. Le C# conserve donc cette possibilité offerte en C/C++ d'adresser directement un char à l'intérieur d'un string d'après sa position comme si on avait déclaré explicitement un char[]. Niveau perfs, y'a pas photo la première ligne sera infiniment plus rapide que de passer par un dictionnaire. Quant à la seconde, ce sera au pire aussi lent. Dans tous les cas, ça consomme 36 octets en mémoire (plus quelques pouillèmes à cause du type String qui est un objet)
 
 
Et pour en revenir au cast explicite :
 

Code :
  1. long MonLong = (long)MonInt;
  2. long MonLong = (long)MonDouble;
  3.  
  4. double MonDouble = (double)MonLong / (double)Monentier;


 
infiniment plus rapide à l'excécution (surtout pour les cast entre int et long qui ont rigougeusement la même représentation au niveau processeur, seul le nombre de registres change, qui est même implicite) :
 

Code :
  1. long MonLong = MonInt;
  2. int MonEntier = MonLong;


 
 
Donc :

Code :
  1. nb += long.Parse(Math.Pow(double.Parse("36" ), scale).ToString()) * tabCorrespondance[var];


 
Devient :

Code :
  1. nb += (long)Math.Pow(36, scale) * tabCorrespondance[var];


 
pas besoin de caster "36", puisqu'une valeur litérale est typée à la compilation avec le type attendu. Il sera déduit du prototype compatible de Math.Pow(?, TypeDe"scale" )
 
En gros, la fonction devient (à 1h du mat, me lourdez pas si ça compile pas :D)

Code :
  1. string const Digits = "0123456789abcdefghijklmnopqrstuvwxyz";
  2.  
  3. public long parseBase(char[] str)
  4. {
  5.  long nb = 0;
  6.  double scale = 0;
  7.  
  8.  for (int i = str.Length - 1; i >= 0; i--)
  9.  {
  10.    nb += (long)Math.Pow(scale++, 36) * Digits.IndexOf(str[i]);
  11.  }
  12.  return nb;
  13. }


 
C un peu plus concis :o


Message édité par MagicBuzz le 04-08-2008 à 01:07:11

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  Parser un long sur une base de 36

 

Sujets relatifs
Deplacer la base de donnees de mysqlScript BATCH avec nom long
Bibliothèque de fonctions PHP 4 pour gérer Base MySQLprobleme de connexion avec ma base oracle
Remplir formulaire PDF avec une base de donnéesinterroger la base de données mysql
[C#] Récuperer le type de base d'un System.NullableURL Rewriting de base...
exportation/importation base MySQLStatistiques base de donnée php
Plus de sujets relatifs à : Parser un long sur une base de 36


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR