Meilleur auteur de réponses
Problèm de manipulation des bits

Question
-
Bonjour,
La question ne vient pas de moi, j'ai tenté d'y répondre mais je ne sais pas trouver le résultat, ça concerne 2 octets mitoyens représentant en binaire une virgule flottante, voici ma réponse, vous comprendrez :o)
(1=signe +4=exposant + 3 = virgule // mantisse = 8) = 16 b
Dim valeurC As String valeurC = "55A0" ' h = 2 octets : 55 h = 85 d Dim octet1H, octet2H As String octet1H = Mid(valeurC, 1, 2) octet2H = Mid(valeurC, 3, 2) Dim octet1D, mantisse As Integer octet1D = Convert.ToInt32(octet1H, 16) ' H(string) en D mantisse = Convert.ToInt32(octet2H, 16) Dim octet1B As String octet1B = Convert.ToString(CLng(octet1D), 2) ' D(string) en B : 01010101 = 85 d Do While Len(octet1B) < 8 ' format à 8 bits (0 devant) octet1B = "0" & octet1B Loop Dim signe As Byte signe = CByte(Mid(octet1B, 1, 1)) If signe < 0 Then mantisse = mantisse * -1 Dim exposantB As String exposantB = Mid(octet1B, 2, 4) Dim virguleB As String virguleB = Mid(octet1B, 6, 3) Dim exposant As Integer exposant = Convert.ToInt32(exposantB, 2) Dim virgule As Integer virgule = Convert.ToInt32(virguleB, 2) Dim formule As String formule = mantisse & "E+" & exposant & " (virgule = " & virgule & ")" ' TextBox1.Text = "valeur = " & valeurC & " h" & vbCrLf TextBox1.Text = TextBox1.Text & "octet1H = " & octet1H & " h (valeur)" & vbCrLf TextBox1.Text = TextBox1.Text & "octet1D = " & octet1D & " d (octet1H)" & vbCrLf TextBox1.Text = TextBox1.Text & "octet1B = " & octet1B & " b (octet1D)" & vbCrLf TextBox1.Text = TextBox1.Text & "octet2H = " & octet2H & " h (valeur)" & vbCrLf TextBox1.Text = TextBox1.Text & "mantisse = " & mantisse & " d (octet2H)" & vbCrLf TextBox1.Text = TextBox1.Text & "signe = " & signe & " d (octet1B)" & vbCrLf TextBox1.Text = TextBox1.Text & "exposantB = " & exposantB & " b (octet1B)" & vbCrLf TextBox1.Text = TextBox1.Text & "exposant = " & exposant & " d (exposantB)" & vbCrLf TextBox1.Text = TextBox1.Text & "virguleB = " & virguleB & " b (octet1B)" & vbCrLf TextBox1.Text = TextBox1.Text & "virgule = " & virgule & " d (virguleB)" & vbCrLf TextBox1.Text = TextBox1.Text & "formule = " & formule & vbCrLf ' ' Je ne sais comment calculer ça ? ' Si c'est mantisse(160) ^ exposant (virgule 5) = 10995,11628 ' Si c'est le nombre de 0 (160E+10) à rajouter (virgule 5), ça donne = 16000 ' ???
Si ma réponse est utile cliquer en haut à gauche sur le triangle vert.
Et
Si la question est résolue, cliquer en bas sur : "Proposer comme réponse"
Cordialement
Joseph Attila PUSZTAY
EhJoe Logiciels Romans Ecrire
Réponses
-
Et du coup, on peut écrire une jolie fonction pour faire ça:
Private Function GetBitsValue(ByVal nombre As Long, _ ByVal bitDepart As Long, _ ByVal nombreBits As Long) As Long Dim mask As Long Dim i As Long Dim temp As Long Dim result As Long temp = bitDepart - nombreBits + 1 ' fabrication du masque For i = bitDepart To temp Step -1 mask = mask Or (2 ^ i) Next i ' masquage result = nombre And mask ' division result = result \ (2 ^ temp) ' retour GetBitsValue = result End Function
POur reprendre l'exemple ci dessus, on veut récupérer 3 bits à partir du bit N° 6 (les bits sont numérotés de droite à gauche en commençant à 0):
donc :
MsgBox GetBitsValue(217, 6, 3)
=> Qui renvoie 5, comme prévu.
Avec cette fonction, les manipulations bitwise deviennent un jeu d'enfant et le code plus lisible, bien sur.
Cordialement,
Jean-marc- Marqué comme réponse EhJoe vendredi 7 janvier 2011 20:41
-
Bonjour Sinki,
J'ai écrit un texte que je vais proposer en FAQ sur la gstion des fichir texte pr les objets, voici le code, suffit de prendre un programme neuf, d'y mettre le code et les objets que k'indique (en vbNet), et chat marche !
' Gestion d'un fichier texte à l'aide des objets ' Option Explicit On ' exemple de gestion d'un fichier texte Public Class Form1 Dim fichier As String = CStr(My.Application.Info.DirectoryPath) & "\test_fic.txt" Dim ligneRajout As String ' ' ------ ' OBJETS ' ------ ' Form1 ' ListBox1 (mettre police fixe, par exp "Courier New" (un seul "R") + laisser "sorted" à "false" ' ListBox2 (idem à listbox1) ' combobox1 ' ' Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim i As Integer = 5 ' création fictives de 5 ensemble comportant 3 sous-ensemble Dim nom(i) As String Dim salaire(i) As String Dim couleurVoiture(i) As String Dim esp As Byte = 0 Dim ligne As String ' Me.Left = 25 Me.Top = 25 Me.Width = 830 Me.Height = 500 ListBox1.Left = 12 ListBox1.Top = 12 ListBox1.Width = 390 ListBox1.Height = 345 ListBox1.Sorted = False ListBox1.Font = New System.Drawing.Font("Courier New", 12) ListBox2.Left = 410 ListBox2.Top = 12 ListBox2.Width = 390 ListBox2.Height = 345 ListBox2.Sorted = False ListBox2.Font = New System.Drawing.Font("Courier New", 12) ComboBox1.Left = 204 ComboBox1.Top = 364 ComboBox1.Width = 525 ComboBox1.Height = 21 ComboBox1.Font = New System.Drawing.Font("Courier New", 12) ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList ComboBox1.Items.Add("Ecrit liste") ComboBox1.Items.Add("Supprime fichier") ComboBox1.Items.Add("Supprime 3e ligne + enregistre") ComboBox1.Items.Add("Rajoute une ligne") ComboBox1.Items.Add("Rajoute en fin de ligne") ComboBox1.Items.Add("REGENERE") ComboBox1.Items.Add("Rajoute en milieu de ligne") ComboBox1.Items.Add("Imprime papier") ComboBox1.Items.Add("Coder/Décoder un texte") ComboBox1.SelectedIndex = 0 ' 'Dupont........ salaire. couleurV 'Durand........ salaire. couleurV 'Saint martin.. salaire. couleurV 'Leroux........ salaire. couleurV 'Lemoine....... salaire. couleurV ' i = 1 ' chargement des variables (normalement saisies) pour démonstrations nom(i) = "Dupont" salaire(i) = "400,12" couleurVoiture(i) = "rouge" i = i + 1 nom(i) = "Durand" salaire(i) = "1000,45" couleurVoiture(i) = "verte" i = i + 1 nom(i) = "Saint martin" salaire(i) = "2000,90" couleurVoiture(i) = "bleue" i = i + 1 nom(i) = "Leroux" salaire(i) = "4000,01" couleurVoiture(i) = "jaune" i = i + 1 nom(i) = "Lemoine" salaire(i) = "8000,00" couleurVoiture(i) = "grise" ' formatage des datas : 16 + 8 + 8 = 32 octets + 2 espaces (+) = ligne de 34 octets ' format pr exp : (nom = 16, salaire 8, couleurVoiture 8) ' le formatage et la vérification se font généralement au moment de la validation de la saisie ' on doit avant vérifier la conformité de la saisie, ce qui n'est pas ici le sujet For i = 1 To 5 ' le nom nom(i) = Mid(nom(i), 1, 16) ' coupe à 16 octets nom(i) = Trim(nom(i)) ' retasse esp = 16 - Len(nom(i)) ' espace 16 octets nom(i) = nom(i) & Space(esp) ' cale à gauche sur 16 octets Next i For i = 1 To 5 ' le salaire salaire(i) = Mid(salaire(i), 1, 8) ' coupe à 8 octets salaire(i) = Trim(salaire(i)) ' retasse esp = 8 - Len(salaire(i)) ' espace 8 octets salaire(i) = Space(esp) & salaire(i) ' cale à droite sur 8 octets Next i For i = 1 To 5 ' la couleur de la voiture couleurVoiture(i) = Mid(couleurVoiture(i), 1, 8) ' coupe à 8 octets couleurVoiture(i) = Trim(couleurVoiture(i)) ' retasse esp = 8 - Len(couleurVoiture(i)) couleurVoiture(i) = couleurVoiture(i) & Space(esp) ' cale à gauche sur 8 octets Next i ' ' vérification de l'existance du fichier, et création si absence ' le fichier texte est par défaut dans c:\...répertoire_actuel\bin\debug ' on teste si le fichier existe ' il semble préférable de créer si besoin le fichier à ce stade où rien n'est affiché ' ainsi, le créant en début, ensuite on pourra l'utiliser en étant certain qu'il existe ' If System.IO.File.Exists(fichier) = True Then Call litFichier() ' le fichier existe, on le lit puis par exp on le charge dans listbox1 Else ' le fichier n'existe pas = création + chargement (ici pour exp) Dim p As New System.IO.StreamWriter(fichier) ' liaison pointeur P avec fichier For i = 1 To 5 ligne = nom(i) & " " & salaire(i) & " " & couleurVoiture(i) p.WriteLine(ligne) ' écriture à la suite ligne se terminant par <cr> (ascii 12+10) Next i p.Close() ' fermeture du fichier Call litFichier() End If End Sub Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged Select Case ComboBox1.SelectedIndex Case 0 : Call ecritFichier() Case 1 : Call supprimeFichier() Case 2 : Call supprimeLigne() Case 3 : Call rajouteLigneEnFin() Case 4 : Call rajouteEnFinDeLigne() Case 5 : Call regenereFichier() Case 6 : Call rajourEnMilieuDeLigne() Case 7 : Call imprimer() Case 8 : Call coderDecoder() End Select End Sub Sub regenereFichier() ListBox1.Items.Clear() ' régénère la list1 d'exemple ListBox1.Items.Add("Dupont 400,12 rouge ") ListBox1.Items.Add("Durand 1000,45 verte ") ListBox1.Items.Add("Saint martin 2000,90 bleue ") ListBox1.Items.Add("Leroux 4000,01 jaune ") ListBox1.Items.Add("Lemoine 8000,00 grise ") Call ecritFichier() End Sub Sub litFichier() ListBox1.Items.Clear() If System.IO.File.Exists(fichier) = False Then Exit Sub If FileLen(fichier) < 1 Then Exit Sub ' si le fichier est vide on sort Dim ligne As String Dim p As New System.IO.StreamReader(fichier) While p.Peek() >= 0 ' avance tant que le pointeur P est > ou = à 0 ligne = p.ReadLine() ' lecture par ligne terminée par <cr> ListBox1.Items.Add(ligne) End While p.Close() End Sub Sub ecritFichier() Dim i As Long If ListBox1.Items.Count < 1 Then Exit Sub ' liste vide, sort ... Dim p As New System.IO.StreamWriter(fichier) For i = 0 To ListBox1.Items.Count - 1 p.WriteLine(ListBox1.Items(i)) ' on peut écrire ou lire directement avec l'objet Next i p.Close() End Sub Sub supprimeFichier() Dim t As String = "Gestion du ficher" ' suppression du fichier Dim m As String = "Supprimer le fichier " Dim y As String y = MessageBox.Show(m, t, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) If y <> vbYes Then Exit Sub Kill(fichier) Call litFichier() End Sub Sub supprimeLigne() If ListBox1.Items.Count < 3 Then Exit Sub ListBox1.Items.RemoveAt(3 - 1) ' supprimer la 3eme ligne / 5 ListBox1.Refresh() Call ecritFichier() End Sub Sub rajouteLigneEnFin() Dim nom As String = "Nom rajouté " ' rajouter une ligne ... en fin Dim salaire As String = " 1234,56" Dim couleurVoiture As String = "ciel " ligneRajout = nom & " " & salaire & " " & couleurVoiture Call rajoutFichier() Call litFichier() End Sub Sub rajouteEnFinDeLigne() If ListBox1.Items.Count < 3 Then Exit Sub ' LE RAJOUT EN FIN D'UNE LIGNE ' rajout en fin de la seconde ligne (veiller à ce que la liste possède 3 lignes au moins) ' Pour cete opération on va utiliser deux listes (mais il y a d'autre méthodes) ' la liste1 va conserver ce qui est avant la ligne à modifier (2e) ' la liste2 va récupérer ce qui est après la ligne modifiée (2e) ' puis on va enlever de la list1 la ligne (2) à modifier ' on modifie la ligne 2 au niveau variables dans le code, puis : ' on remet la line modifiée à la list1 à laquelle on ajoute ensuite la list2 ' enfin on inject dans le fichier en écrasement création la list1 ' Dim rajoutEnFin As String = " ©" ' à rajouter en fin de la ligne 2 Dim i As Long ListBox2.Items.Clear() For i = 2 To ListBox1.Items.Count - 1 ' on met en list2 ce qui est après la ligne à modifier de la list1 ListBox2.Items.Add(ListBox1.Items(i)) Next i ' la list1 conserve tout jusqu'à la ligne à modifier incluse For i = ListBox1.Items.Count - 1 To 2 Step -1 ' stop juste avant ligne à modifier ListBox1.Items.RemoveAt(i) ' on efface list1 ce qui passe en list2 Next i ' la list1 conserve tout jusqu'à la ligne à modifier incluse ligneRajout = ListBox1.Items(1) ' 2eme ligne (devenue dernière) en partant de 0, copié dans la variable ListBox1.Items.RemoveAt(1) ' on enlève de la list1 la ligne a modifier qui est copiée en variable ListBox1.Refresh() ligneRajout = ligneRajout & rajoutEnFin ' on rajoute l'élement à la ligne à modifier ListBox1.Items.Add(ligneRajout) ' on remet à sa place la ligne modifiée en list1 For i = 0 To ListBox2.Items.Count - 1 ListBox1.Items.Add(ListBox2.Items(i)) ' on met en fin de list1 le contenu de list2 Next i Call ecritFichier() ' on écrit toute la liste1 dans le fichier par écrasement End Sub Sub rajourEnMilieuDeLigne() If ListBox1.Items.Count < 3 Then Exit Sub ' voir la méthode de la procédure : "rajouteEnFinDeLigne()" Dim m As String ' à rajouter en fin de la ligne 2 Dim r As String = "@" ' rajout Dim i As Long Dim un As String Dim deux As String ListBox2.Items.Clear() For i = 2 To ListBox1.Items.Count - 1 ListBox2.Items.Add(ListBox1.Items(i)) Next i For i = ListBox1.Items.Count - 1 To 2 Step -1 ListBox1.Items.RemoveAt(i) Next i m = ListBox1.Items(1) ListBox1.Items.RemoveAt(1) ListBox1.Refresh() un = Mid(m, 1, 26) ' on scinde en deux, avant et après l'insertion deux = Mid(m, 27, 8) m = un & r & deux ' on insère et on réuni de nouveau ListBox1.Items.Add(m) For i = 0 To ListBox2.Items.Count - 1 ListBox1.Items.Add(ListBox2.Items(i)) Next i Call ecritFichier() End Sub Sub rajoutFichier() ' 2 écriture (création et rajout) ... voir ci-dessus Dim p As New System.IO.StreamWriter(fichier, True) ' TRUE = créer et si existe = AJOUT p.WriteLine(ligneRajout) p.Close() End Sub Sub coderDecoder() Dim ligne As String Dim mot As String = "monMotDePasse" Dim ascii As Integer Dim saut As String = vbLf Dim octet As Char Dim alternat As Double Dim code As String ' ligne = "MOT A CODER" & saut & saut & mot & saut & saut alternat = -1 ' codage code = "" For i = 1 To Len(mot) ascii = Asc(Mid(mot, i, 1)) octet = Chr(ascii + alternat) code = code & octet alternat = alternat * -1 Next i ligne = ligne & saut & "MOT CODE" & saut & saut & code & saut & saut & saut & "MOT DECODE" & saut & saut alternat = 1 mot = "" For i = 1 To Len(code) ' décodage ascii = Asc(Mid(code, i, 1)) octet = Chr(ascii + alternat) mot = mot & octet alternat = alternat * -1 Next i ligne = ligne & mot & saut MsgBox(ligne, MsgBoxStyle.Information) End Sub Sub imprimer() PrintDocument1.Print() End Sub Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage Dim i As Integer Dim ligne As String = "" If ListBox1.Items.Count < 1 Then Exit Sub For i = 0 To ListBox1.Items.Count - 1 ligne = ligne & ListBox1.Items(i) & vbCrLf Next i e.Graphics.DrawString(ligne, New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 150, 125) End Sub Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing End End Sub End Class
Alors te concernant et pour tes réponse, bien que ce serait mieux dans le foruml vbNet, voici :
Pour les deux octets, en effet il me semble bien que la virgule flottante se gère à partir d'au moins 4 octets en single donc pour VB, tu semble satisfait du résultat, certes, mais il faut être certain qu'il est bon, il faudrait pouvoir comparer, car toi tu as ça sur 2 octets, Jean-Marc est très compétent en la matière, mais il faudrait pour être certain, passer un nombre connu en la forme reçue, puis appliquer la fonction afin de voir s'il est recomposé à l'origine. Le décélage à droite et gauche permet en effet une sorte d'élimination de certains bits, afin de conserver ceux qu'on veut lire et de le faire directement, ça revient au même de les lire textuellement, mais la vrai méthode est le décalage (c'est rare d'avoir à faire ça) ...
Il faut aussi se méfier, il me semble que vbNet a changé la taille des variables, par exemple integer (short) jadis faisait 2 octet, je crois que désormais il en fait 4, tout est décalé comme ça afin de conserver les mêmes noms mais de couvrir le 64 bits (8 cotets), à vérifier dans la doc ...
Pour ma part quand je le peux, afin d'éviter toute salade, je mets toujours les nombres textuellement et cadrés dans les fichiers, ainsi y a ps de lézard de pécision ensuite, comme tu le soulignes, la virgule flottante a une précision relative ...
Pour tes labels, en ligne ça peut petre mieux, bien cadrés, 20 par ligne, je fais comme si tu les avais indicés afin de simplifier, en fait c'est davantage de la manipulation de chaînes qu'autre chose :
' dim i as integer = 0 label de 1 à 20 = l(i) ' dim tot as string = "" for i = 1 to 20 if i < 20 then tot = tot & format(l(i),"000.00") & ";" if i = 20 then tot = tot & format(l(i),"000.00") next i ' puis tu balances t dans le fichier en ajout, tu as un txt avec séparateur ";" ' ' Pour le timer tu autorise l'enregistrement tous le x secones, choix par comboBox, comme ça y a pas de doute, puis tu enregistre cette préférence dans un autre fichier en écrasement création, donc on lit le fichier à l'ouverture, et on le crée s'il n'existe pas ou s'il est vide en le chargeant avec une valeur par défaut, ainsi, en prenant l'exemple sur un Timer qui enregistrerait toutes les secondes et ton texte boxe qui proposerait seconde par seconde évidemment : ' dim t as integer = combobox1.text ' global dim avance as integer = 0 ' global ' sub timer1... avance = avance + 1 ' seconde if avance = t then avance = 0 ' tu bamances la ligne to dans le fichier end if end sub ' timer1 '
Ben je crois que c'est tout, sinon repasse sur vbNet, question genre "gérer fichier txt" ou "gérer chaînesé", et tu m'envoies un mail si tu veux que je vienne (montmartre75018 arobase free point fr)
Si ma réponse est utile cliquer en haut à gauche sur le triangle vert.
Et
Si la question est résolue, cliquer en bas sur : "Proposer comme réponse"
Cordialement
Joseph Attila PUSZTAY
EhJoe Logiciels Romans Ecrire- Marqué comme réponse EhJoe samedi 8 janvier 2011 12:46
-
Bonjour Sinki,
C'est vrai qu'il vaut mieux aller dans le forum vbNet, voici :
' Dim o As New Collection() ' débute à 1 o.Add(Me.Label1) ' o(i) indice les objets o.Add(Me.Label2) ' o(i) indice les objets o.Add(Me.Label2) ' o(i) indice les objets ' ... ' ' ne pas oublier la fin de l'entête (nom des objets) ' Sub Label1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label1.Click, Label2.Click, Label3.Click ' ... End Sub ' sub ...' utilisation dim i as long o(i).text = "ton texte label i" end sub '
Si ma réponse est utile cliquer en haut à gauche sur le triangle vert.
Et
Si la question est résolue, cliquer en bas sur : "Proposer comme réponse"
Cordialement
Joseph Attila PUSZTAY
EhJoe Logiciels Romans Ecrire- Marqué comme réponse EhJoe samedi 8 janvier 2011 15:53
Toutes les réponses
-
Hello,
le principe est expliqué ici, c'est tout simple:
http://fr.wikipedia.org/wiki/IEEE_754
(tu adapteras un minimum, car en simple précision, on a toujours au moins 4 octets normalement, mais ça ne change rien au principe de toute façon)
Au niveau méthode:
A noter tout de même que VB te permet de manipuler les octets bits à bits de façon simple avec l'opérateur "AND". J'ai écrit des tonnes de trucs sur le sujet sur feu le newsfroup usenet...
Soit un octet (8 bits) comme ceci "XAAA XXXX"; je veux récupérer la valeur de "AAA"
Soit V la valeur de cet octet.
Soit A la variable ou je vais récupérer la valeur de AAA
1) masqer tous bits sauf ceux correspondant à AAA, soit en binaire "0111 0000" = en décimal : 7*16+0 = 112
A = V AND 112
2) décaler à droite du bon nombre de positions (ici : de 4).
un décalage à droite revient à une division par 2. On doit décaler 4 fois, donc on divise par 2*2*2*2 = 16
A = A / 16
et voila.
Exemple numérique.
Soit V = 217
Note : 217 = D9 en hexa = 1101 1001 en binaire. on cherche AAA (donc ici c'est 101 en binaire qui vaut 5 en décimal); notre A final doit donc valoir 5.
Appliquons la méthode indiqué précédemment:
1) masquage
A = V AND 112 = 80 en décimal (ce qui fait 0101 0000 en binaire )
2) division
A = A/16 = 80/16 = 5 ; A = 5
On a bien retrouvé 5; tout roule donc, la méthode indiqué fonctionne.
Bonne suite!
Jean-marc- Proposé comme réponse Alex Petrescu vendredi 7 janvier 2011 15:37
-
Et du coup, on peut écrire une jolie fonction pour faire ça:
Private Function GetBitsValue(ByVal nombre As Long, _ ByVal bitDepart As Long, _ ByVal nombreBits As Long) As Long Dim mask As Long Dim i As Long Dim temp As Long Dim result As Long temp = bitDepart - nombreBits + 1 ' fabrication du masque For i = bitDepart To temp Step -1 mask = mask Or (2 ^ i) Next i ' masquage result = nombre And mask ' division result = result \ (2 ^ temp) ' retour GetBitsValue = result End Function
POur reprendre l'exemple ci dessus, on veut récupérer 3 bits à partir du bit N° 6 (les bits sont numérotés de droite à gauche en commençant à 0):
donc :
MsgBox GetBitsValue(217, 6, 3)
=> Qui renvoie 5, comme prévu.
Avec cette fonction, les manipulations bitwise deviennent un jeu d'enfant et le code plus lisible, bien sur.
Cordialement,
Jean-marc- Marqué comme réponse EhJoe vendredi 7 janvier 2011 20:41
-
Bonsoir Jean-marc,
Je suis a l'orgine de la question posée par EhJoe, qui tres bien repondu a ma demande. Votre fonction fonctionne.
Seulement il nous reste un point a resoudre, celui du resultat de la mantisse, qui est une fraction binaire sur 11 bits. (Voir detail sur reponse faite EhJoe)
Je pensais faire une comparaison bit a bit par seletcase, et renvoi sur un case si vrai. (Pas tres clair tous ca....!)
Aurriez vous une solution, plus pro et plus propre ?
Merci.
-
Bonsoir,
je ne comprend pas ce qu'il faut faire en pratique, j'ai juste répondu sur la partie technique d'extraction des bits.
Mais Si tu as un exemple numérique et le détail du calcul à faire (explication pas à pas, à la main), je pourrais sans doute proposer une réponse.
(donc un truc du genre : "la valeur initiale est 55A0 et on doit trouver 42,789 car le calcul est ... N'hésite pas à donner tous les détails, le découpage manuel et tout et tout.)
Cordialement,
Jean-marc -
Re bonsoir,
Voici un exemple de mon application :
L'ecriture d'un nombre flottant selon la norme IEEE754, demi precision(16bits) est comme ceux-ci : 1bit de signe, 5 bits d'exposant, 10 bits de mantisse.
dans ce cas la formule= signe * 2^exposant-15 * 1.mantisse
Ce qui n'est pas tous a fait mon cas, puisque j'ai 4 bits d'exposant et 11 bits de mantisse.
le resultat qui s'en decoule est : formule= signe * 2^exposant-7 * 1.mantisse
la mantisse est comprise entre 0 et <1, et elle est calculée comme ceux-ci : ( 2^-1+2^-2+2^-3+2^-4.......2^-11) = (0.5+0.25+0.125+0.0625......+0,00048828125)
Dans mon exemple :
Byte 1 = 55h = 01010101
Byte 2 =A0h = 10100000
Signe= 0 = positif =1
Exposant = 1010 = 10
Mantisse = 10110100000= 0.5 + 0 + 0.125 + 0.0625 + 0 + 0.015625 =0.703125
Valeur = 1 * 2 ^ 10-7 * 1.703125 = 13.625
-
Parfait c'est clair.
Voici donc la fonction, toute simple:
Private Function Decode(ByVal v As Long) As Double Dim signe As Long Dim exposant As Long Dim mantisse As Long Dim mantisseDouble As Double Dim n As Long Dim i As Long Dim result As Double signe = IIf(GetBitsValue(v, 15, 1) = 0, 1, -1) exposant = GetBitsValue(v, 14, 4) mantisse = GetBitsValue(v, 10, 11) For i = 10 To 0 Step -1 n = n + 1 mantisseDouble = mantisseDouble + ((2 ^ (-n)) * GetBitsValue(mantisse, i, 1)) Next i result = signe * 2 ^ (exposant - 7) * (1 + mantisseDouble) Decode = result End Function
Et voila :
MsgBox Decode(&H55A0)
retourne : 13,625
L'astuce est juste dans la boucle, en réutilisant getbitsvalue sur la mantisse elle même, puisque c'est finalement ça qu'on veut :-)
(et merci pour cet amusant exercice, je n'avais pas fait d'arithmetique binaire en VB depuis un petit temps :-) )
Cordialement;
Jean-marc- Proposé comme réponse Sinki42 vendredi 7 janvier 2011 21:59
-
LES Mircales de l'informatique, fait par des dieux de l'informatiqiue !
Tres tres beau code, parfait pour mon application. Du vrai code de pro en moins de 10 minutes, alors que je cherche une solution depuis, ouh... !
Felicitation, bravo et chapeau bas !
Une petite chose encore : La valeur que je dois coder, arrive depuis mon port serie, sur 2 bytes differents, comment les reunires ?
Merci encore,
Encore merci.
-
Hello,
merci :o)
Pour réunir tes 2 bytes, c'est tout simple
Disons que tu reçois d'abord le byte de poids le plus fort (55 dans notre example) puis celui de poids le plus faible (A0 dans notre example.
Tu as donc 2 bytes reçus en série:
BH (=&h55 = 85 en décimal)
BL (=&hA0 = 160 en décimal)
Ta valeur est tout bonnement BH * 256 + BL;
application
&H55A0 vaut 21920 en décimal
BH * 256 + BL = 85 * 256 + 160 = 21760 + 160 = 21920 ; le compte est bon :-)
Cordialement;
Jean-marc- Proposé comme réponse Sinki42 vendredi 7 janvier 2011 22:22
-
-
Re Bonsoir,
Merci merci, mais c'est trop d'honneur :-)
Blague à part, ce n'est "que" le résultat de 30 ans de pratique assidue, sans compter la lecture de quelques dizaines de bouquins, quelques années d'étude et bien sur, beaucoup de passion pour la chose !
Très bonne soirée à toi aussi, et à bientôt certainement :-)
Cordialement,
Jean-marc -
Bonjour Jean-Marc,
"Oui mais" ... ça c'est quand c'est du unsigned short, mais dans notre cas tu as une virgule, il faut bien aller lire sa position dans l'octet de poids fort, et c'est là où je ne suis plus, car si le premier octet dans l'exemple est la mantisse, ok, ça se transforme directement, mais le second octet n'est pas une valeur en tant que telle, elle se décompose en trois sous valeur (signe, exposant et virgule), alors on ne peut pas dans ce cas prendre le premier octet comme si c'était aussi un mantisse, il faut manifestement recomposer la notation (exposant, nantisse), sans doute dans le style Excel (?) : xE+y, non ?
Si ma réponse est utile cliquer en haut à gauche sur le triangle vert.
Et
Si la question est résolue, cliquer en bas sur : "Proposer comme réponse"
Cordialement
Joseph Attila PUSZTAY
EhJoe Logiciels Romans Ecrire -
Bonjour Joseph,
Je pense que tu "bloque" sur la virgule. Elle faite automatiquement dans le calcul de la valeur finale, dans la partie (1 + mantisseDouble).
Ca fonctionne tres bien dans notre cas, elle donne un single, comme le fait implicitement VB ou tout autre langage informatique, puisque un nombre a virgule flottante est une valeur approchée avec plus ou moins de precision (voir norme IEEE754).
Sauf que dans mon cas, les modules avec lesquels je communique, me transmettent des valeurs selon la norme IEEE754 demi-precision ( Et encore pas tout a fait, puisque je n'ai que 4 bits d'exposant au lieu de 5, d'où la fonction de Jean-marc).
Je profite de post, pour demander encore un peu d'aide :
Je recois donc des valeurs, mises en forme selon la fonction de Jean-marc. Ces valeurs je les affiches dans des Labels,que je met a jour toutes les seconde,jusque là tous va bien.
Je souhaiterais enregistrer les valeurs contenus dans ces labels, selon une periode defini par l'operateur, de maniere a pouvoir etre analysées plus tard (Graph,courbes...).
Exemple :
t etant ma periode= 15 minutes,
E etant l'enregistrement
à E=E+t=15 à E=E+t=30 à E=E+t=45
label1=5.5 label1=5.2 label1=5.3
label2=5.5 label2=5.1 label2=5.0
label3=5.2 label3=5.2 label3=5.3
...label20=4.9
Je devrais obtenir un fichier avec ces valeurs de temps et de label ( plus quelques info sur l'operateur par exemple;)
Merci pour vous reponses.
Salutations.
Sinki.
-
Bonjour Sinki,
J'ai écrit un texte que je vais proposer en FAQ sur la gstion des fichir texte pr les objets, voici le code, suffit de prendre un programme neuf, d'y mettre le code et les objets que k'indique (en vbNet), et chat marche !
' Gestion d'un fichier texte à l'aide des objets ' Option Explicit On ' exemple de gestion d'un fichier texte Public Class Form1 Dim fichier As String = CStr(My.Application.Info.DirectoryPath) & "\test_fic.txt" Dim ligneRajout As String ' ' ------ ' OBJETS ' ------ ' Form1 ' ListBox1 (mettre police fixe, par exp "Courier New" (un seul "R") + laisser "sorted" à "false" ' ListBox2 (idem à listbox1) ' combobox1 ' ' Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim i As Integer = 5 ' création fictives de 5 ensemble comportant 3 sous-ensemble Dim nom(i) As String Dim salaire(i) As String Dim couleurVoiture(i) As String Dim esp As Byte = 0 Dim ligne As String ' Me.Left = 25 Me.Top = 25 Me.Width = 830 Me.Height = 500 ListBox1.Left = 12 ListBox1.Top = 12 ListBox1.Width = 390 ListBox1.Height = 345 ListBox1.Sorted = False ListBox1.Font = New System.Drawing.Font("Courier New", 12) ListBox2.Left = 410 ListBox2.Top = 12 ListBox2.Width = 390 ListBox2.Height = 345 ListBox2.Sorted = False ListBox2.Font = New System.Drawing.Font("Courier New", 12) ComboBox1.Left = 204 ComboBox1.Top = 364 ComboBox1.Width = 525 ComboBox1.Height = 21 ComboBox1.Font = New System.Drawing.Font("Courier New", 12) ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList ComboBox1.Items.Add("Ecrit liste") ComboBox1.Items.Add("Supprime fichier") ComboBox1.Items.Add("Supprime 3e ligne + enregistre") ComboBox1.Items.Add("Rajoute une ligne") ComboBox1.Items.Add("Rajoute en fin de ligne") ComboBox1.Items.Add("REGENERE") ComboBox1.Items.Add("Rajoute en milieu de ligne") ComboBox1.Items.Add("Imprime papier") ComboBox1.Items.Add("Coder/Décoder un texte") ComboBox1.SelectedIndex = 0 ' 'Dupont........ salaire. couleurV 'Durand........ salaire. couleurV 'Saint martin.. salaire. couleurV 'Leroux........ salaire. couleurV 'Lemoine....... salaire. couleurV ' i = 1 ' chargement des variables (normalement saisies) pour démonstrations nom(i) = "Dupont" salaire(i) = "400,12" couleurVoiture(i) = "rouge" i = i + 1 nom(i) = "Durand" salaire(i) = "1000,45" couleurVoiture(i) = "verte" i = i + 1 nom(i) = "Saint martin" salaire(i) = "2000,90" couleurVoiture(i) = "bleue" i = i + 1 nom(i) = "Leroux" salaire(i) = "4000,01" couleurVoiture(i) = "jaune" i = i + 1 nom(i) = "Lemoine" salaire(i) = "8000,00" couleurVoiture(i) = "grise" ' formatage des datas : 16 + 8 + 8 = 32 octets + 2 espaces (+) = ligne de 34 octets ' format pr exp : (nom = 16, salaire 8, couleurVoiture 8) ' le formatage et la vérification se font généralement au moment de la validation de la saisie ' on doit avant vérifier la conformité de la saisie, ce qui n'est pas ici le sujet For i = 1 To 5 ' le nom nom(i) = Mid(nom(i), 1, 16) ' coupe à 16 octets nom(i) = Trim(nom(i)) ' retasse esp = 16 - Len(nom(i)) ' espace 16 octets nom(i) = nom(i) & Space(esp) ' cale à gauche sur 16 octets Next i For i = 1 To 5 ' le salaire salaire(i) = Mid(salaire(i), 1, 8) ' coupe à 8 octets salaire(i) = Trim(salaire(i)) ' retasse esp = 8 - Len(salaire(i)) ' espace 8 octets salaire(i) = Space(esp) & salaire(i) ' cale à droite sur 8 octets Next i For i = 1 To 5 ' la couleur de la voiture couleurVoiture(i) = Mid(couleurVoiture(i), 1, 8) ' coupe à 8 octets couleurVoiture(i) = Trim(couleurVoiture(i)) ' retasse esp = 8 - Len(couleurVoiture(i)) couleurVoiture(i) = couleurVoiture(i) & Space(esp) ' cale à gauche sur 8 octets Next i ' ' vérification de l'existance du fichier, et création si absence ' le fichier texte est par défaut dans c:\...répertoire_actuel\bin\debug ' on teste si le fichier existe ' il semble préférable de créer si besoin le fichier à ce stade où rien n'est affiché ' ainsi, le créant en début, ensuite on pourra l'utiliser en étant certain qu'il existe ' If System.IO.File.Exists(fichier) = True Then Call litFichier() ' le fichier existe, on le lit puis par exp on le charge dans listbox1 Else ' le fichier n'existe pas = création + chargement (ici pour exp) Dim p As New System.IO.StreamWriter(fichier) ' liaison pointeur P avec fichier For i = 1 To 5 ligne = nom(i) & " " & salaire(i) & " " & couleurVoiture(i) p.WriteLine(ligne) ' écriture à la suite ligne se terminant par <cr> (ascii 12+10) Next i p.Close() ' fermeture du fichier Call litFichier() End If End Sub Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged Select Case ComboBox1.SelectedIndex Case 0 : Call ecritFichier() Case 1 : Call supprimeFichier() Case 2 : Call supprimeLigne() Case 3 : Call rajouteLigneEnFin() Case 4 : Call rajouteEnFinDeLigne() Case 5 : Call regenereFichier() Case 6 : Call rajourEnMilieuDeLigne() Case 7 : Call imprimer() Case 8 : Call coderDecoder() End Select End Sub Sub regenereFichier() ListBox1.Items.Clear() ' régénère la list1 d'exemple ListBox1.Items.Add("Dupont 400,12 rouge ") ListBox1.Items.Add("Durand 1000,45 verte ") ListBox1.Items.Add("Saint martin 2000,90 bleue ") ListBox1.Items.Add("Leroux 4000,01 jaune ") ListBox1.Items.Add("Lemoine 8000,00 grise ") Call ecritFichier() End Sub Sub litFichier() ListBox1.Items.Clear() If System.IO.File.Exists(fichier) = False Then Exit Sub If FileLen(fichier) < 1 Then Exit Sub ' si le fichier est vide on sort Dim ligne As String Dim p As New System.IO.StreamReader(fichier) While p.Peek() >= 0 ' avance tant que le pointeur P est > ou = à 0 ligne = p.ReadLine() ' lecture par ligne terminée par <cr> ListBox1.Items.Add(ligne) End While p.Close() End Sub Sub ecritFichier() Dim i As Long If ListBox1.Items.Count < 1 Then Exit Sub ' liste vide, sort ... Dim p As New System.IO.StreamWriter(fichier) For i = 0 To ListBox1.Items.Count - 1 p.WriteLine(ListBox1.Items(i)) ' on peut écrire ou lire directement avec l'objet Next i p.Close() End Sub Sub supprimeFichier() Dim t As String = "Gestion du ficher" ' suppression du fichier Dim m As String = "Supprimer le fichier " Dim y As String y = MessageBox.Show(m, t, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) If y <> vbYes Then Exit Sub Kill(fichier) Call litFichier() End Sub Sub supprimeLigne() If ListBox1.Items.Count < 3 Then Exit Sub ListBox1.Items.RemoveAt(3 - 1) ' supprimer la 3eme ligne / 5 ListBox1.Refresh() Call ecritFichier() End Sub Sub rajouteLigneEnFin() Dim nom As String = "Nom rajouté " ' rajouter une ligne ... en fin Dim salaire As String = " 1234,56" Dim couleurVoiture As String = "ciel " ligneRajout = nom & " " & salaire & " " & couleurVoiture Call rajoutFichier() Call litFichier() End Sub Sub rajouteEnFinDeLigne() If ListBox1.Items.Count < 3 Then Exit Sub ' LE RAJOUT EN FIN D'UNE LIGNE ' rajout en fin de la seconde ligne (veiller à ce que la liste possède 3 lignes au moins) ' Pour cete opération on va utiliser deux listes (mais il y a d'autre méthodes) ' la liste1 va conserver ce qui est avant la ligne à modifier (2e) ' la liste2 va récupérer ce qui est après la ligne modifiée (2e) ' puis on va enlever de la list1 la ligne (2) à modifier ' on modifie la ligne 2 au niveau variables dans le code, puis : ' on remet la line modifiée à la list1 à laquelle on ajoute ensuite la list2 ' enfin on inject dans le fichier en écrasement création la list1 ' Dim rajoutEnFin As String = " ©" ' à rajouter en fin de la ligne 2 Dim i As Long ListBox2.Items.Clear() For i = 2 To ListBox1.Items.Count - 1 ' on met en list2 ce qui est après la ligne à modifier de la list1 ListBox2.Items.Add(ListBox1.Items(i)) Next i ' la list1 conserve tout jusqu'à la ligne à modifier incluse For i = ListBox1.Items.Count - 1 To 2 Step -1 ' stop juste avant ligne à modifier ListBox1.Items.RemoveAt(i) ' on efface list1 ce qui passe en list2 Next i ' la list1 conserve tout jusqu'à la ligne à modifier incluse ligneRajout = ListBox1.Items(1) ' 2eme ligne (devenue dernière) en partant de 0, copié dans la variable ListBox1.Items.RemoveAt(1) ' on enlève de la list1 la ligne a modifier qui est copiée en variable ListBox1.Refresh() ligneRajout = ligneRajout & rajoutEnFin ' on rajoute l'élement à la ligne à modifier ListBox1.Items.Add(ligneRajout) ' on remet à sa place la ligne modifiée en list1 For i = 0 To ListBox2.Items.Count - 1 ListBox1.Items.Add(ListBox2.Items(i)) ' on met en fin de list1 le contenu de list2 Next i Call ecritFichier() ' on écrit toute la liste1 dans le fichier par écrasement End Sub Sub rajourEnMilieuDeLigne() If ListBox1.Items.Count < 3 Then Exit Sub ' voir la méthode de la procédure : "rajouteEnFinDeLigne()" Dim m As String ' à rajouter en fin de la ligne 2 Dim r As String = "@" ' rajout Dim i As Long Dim un As String Dim deux As String ListBox2.Items.Clear() For i = 2 To ListBox1.Items.Count - 1 ListBox2.Items.Add(ListBox1.Items(i)) Next i For i = ListBox1.Items.Count - 1 To 2 Step -1 ListBox1.Items.RemoveAt(i) Next i m = ListBox1.Items(1) ListBox1.Items.RemoveAt(1) ListBox1.Refresh() un = Mid(m, 1, 26) ' on scinde en deux, avant et après l'insertion deux = Mid(m, 27, 8) m = un & r & deux ' on insère et on réuni de nouveau ListBox1.Items.Add(m) For i = 0 To ListBox2.Items.Count - 1 ListBox1.Items.Add(ListBox2.Items(i)) Next i Call ecritFichier() End Sub Sub rajoutFichier() ' 2 écriture (création et rajout) ... voir ci-dessus Dim p As New System.IO.StreamWriter(fichier, True) ' TRUE = créer et si existe = AJOUT p.WriteLine(ligneRajout) p.Close() End Sub Sub coderDecoder() Dim ligne As String Dim mot As String = "monMotDePasse" Dim ascii As Integer Dim saut As String = vbLf Dim octet As Char Dim alternat As Double Dim code As String ' ligne = "MOT A CODER" & saut & saut & mot & saut & saut alternat = -1 ' codage code = "" For i = 1 To Len(mot) ascii = Asc(Mid(mot, i, 1)) octet = Chr(ascii + alternat) code = code & octet alternat = alternat * -1 Next i ligne = ligne & saut & "MOT CODE" & saut & saut & code & saut & saut & saut & "MOT DECODE" & saut & saut alternat = 1 mot = "" For i = 1 To Len(code) ' décodage ascii = Asc(Mid(code, i, 1)) octet = Chr(ascii + alternat) mot = mot & octet alternat = alternat * -1 Next i ligne = ligne & mot & saut MsgBox(ligne, MsgBoxStyle.Information) End Sub Sub imprimer() PrintDocument1.Print() End Sub Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage Dim i As Integer Dim ligne As String = "" If ListBox1.Items.Count < 1 Then Exit Sub For i = 0 To ListBox1.Items.Count - 1 ligne = ligne & ListBox1.Items(i) & vbCrLf Next i e.Graphics.DrawString(ligne, New Font("Courier New", 12, FontStyle.Bold), Brushes.Black, 150, 125) End Sub Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing End End Sub End Class
Alors te concernant et pour tes réponse, bien que ce serait mieux dans le foruml vbNet, voici :
Pour les deux octets, en effet il me semble bien que la virgule flottante se gère à partir d'au moins 4 octets en single donc pour VB, tu semble satisfait du résultat, certes, mais il faut être certain qu'il est bon, il faudrait pouvoir comparer, car toi tu as ça sur 2 octets, Jean-Marc est très compétent en la matière, mais il faudrait pour être certain, passer un nombre connu en la forme reçue, puis appliquer la fonction afin de voir s'il est recomposé à l'origine. Le décélage à droite et gauche permet en effet une sorte d'élimination de certains bits, afin de conserver ceux qu'on veut lire et de le faire directement, ça revient au même de les lire textuellement, mais la vrai méthode est le décalage (c'est rare d'avoir à faire ça) ...
Il faut aussi se méfier, il me semble que vbNet a changé la taille des variables, par exemple integer (short) jadis faisait 2 octet, je crois que désormais il en fait 4, tout est décalé comme ça afin de conserver les mêmes noms mais de couvrir le 64 bits (8 cotets), à vérifier dans la doc ...
Pour ma part quand je le peux, afin d'éviter toute salade, je mets toujours les nombres textuellement et cadrés dans les fichiers, ainsi y a ps de lézard de pécision ensuite, comme tu le soulignes, la virgule flottante a une précision relative ...
Pour tes labels, en ligne ça peut petre mieux, bien cadrés, 20 par ligne, je fais comme si tu les avais indicés afin de simplifier, en fait c'est davantage de la manipulation de chaînes qu'autre chose :
' dim i as integer = 0 label de 1 à 20 = l(i) ' dim tot as string = "" for i = 1 to 20 if i < 20 then tot = tot & format(l(i),"000.00") & ";" if i = 20 then tot = tot & format(l(i),"000.00") next i ' puis tu balances t dans le fichier en ajout, tu as un txt avec séparateur ";" ' ' Pour le timer tu autorise l'enregistrement tous le x secones, choix par comboBox, comme ça y a pas de doute, puis tu enregistre cette préférence dans un autre fichier en écrasement création, donc on lit le fichier à l'ouverture, et on le crée s'il n'existe pas ou s'il est vide en le chargeant avec une valeur par défaut, ainsi, en prenant l'exemple sur un Timer qui enregistrerait toutes les secondes et ton texte boxe qui proposerait seconde par seconde évidemment : ' dim t as integer = combobox1.text ' global dim avance as integer = 0 ' global ' sub timer1... avance = avance + 1 ' seconde if avance = t then avance = 0 ' tu bamances la ligne to dans le fichier end if end sub ' timer1 '
Ben je crois que c'est tout, sinon repasse sur vbNet, question genre "gérer fichier txt" ou "gérer chaînesé", et tu m'envoies un mail si tu veux que je vienne (montmartre75018 arobase free point fr)
Si ma réponse est utile cliquer en haut à gauche sur le triangle vert.
Et
Si la question est résolue, cliquer en bas sur : "Proposer comme réponse"
Cordialement
Joseph Attila PUSZTAY
EhJoe Logiciels Romans Ecrire- Marqué comme réponse EhJoe samedi 8 janvier 2011 12:46
-
-
Hello,
il est sans doute judicieux de créer un nouveau sujet pour cette nouvelle question, car elle n'est plus du tout en rapport avec la question originale.
D'autre part, j'ai cru comprendre que tu programmais en vb.net ? Si c'est le cas, il serait aussi plus judicieux de poursuivre cet échange dans le bon forum.
Si tu es en VB6, alors pas de problème : ceci est le bon endroit et tu peux y créer la nouvelle question.
Cordialement,;
Jean-marc -
Bonjour Sinki,
C'est vrai qu'il vaut mieux aller dans le forum vbNet, voici :
' Dim o As New Collection() ' débute à 1 o.Add(Me.Label1) ' o(i) indice les objets o.Add(Me.Label2) ' o(i) indice les objets o.Add(Me.Label2) ' o(i) indice les objets ' ... ' ' ne pas oublier la fin de l'entête (nom des objets) ' Sub Label1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label1.Click, Label2.Click, Label3.Click ' ... End Sub ' sub ...' utilisation dim i as long o(i).text = "ton texte label i" end sub '
Si ma réponse est utile cliquer en haut à gauche sur le triangle vert.
Et
Si la question est résolue, cliquer en bas sur : "Proposer comme réponse"
Cordialement
Joseph Attila PUSZTAY
EhJoe Logiciels Romans Ecrire- Marqué comme réponse EhJoe samedi 8 janvier 2011 15:53