Convert.ToInt32 [Résolu]

Messages postés
15
Date d'inscription
jeudi 21 août 2003
Dernière intervention
4 mars 2011
- - Dernière réponse : cs_kraven
Messages postés
13
Date d'inscription
jeudi 30 août 2001
Dernière intervention
13 novembre 2013
- 3 mars 2011 à 07:44
Bonjour,

Voilà, cela fais plusieurs année que je m'inspire de ce forum à je trouve toutes mes informations. Par contre cette fois je suis face à un problème ou même google mon ami n'est pas parvenu à résoudre :-)

j'ai cette fonction

Public Function NumericAddress(ByVal address As [String]) As Integer

        'Converti les adresse de group au format du bus
        Dim token As String() = address.Split("/")

        If token.Length <> 3 Then

            Return 0

        Else

            Dim main As Integer = Convert.ToInt32(token(0))
            Dim middle As Integer = Convert.ToInt32(token(1))
            Dim sube As Integer = Convert.ToInt32(token(2))

            Return (main << 11) Or (middle << 8) Or (sube)


        End If

    End Function


Donc quand je fais cela : MsgBox("1/0/11 donne : " & NumericAddress("1/0/11")) j'ai comme retours 2059. Jusque là tout est OK !!!

Maintenant je voudrais faire le contraire. Je voudrais créer une fonction ou si je donne 2059 il me retourne 1/0/11, mais cela fais plusieurs jour que je suis dessus sans réussir.

Je vous remercie déjà de votre aide.

Kristof
Afficher la suite 

Votre réponse

13 réponses

Meilleure réponse
Messages postés
107
Date d'inscription
samedi 25 novembre 2000
Dernière intervention
4 mai 2013
3
Merci
Bonjour,

Si on prend ton exemple, tu pars de "1/0/11" et tu obtiens 2059. On remarque de plus que,
2059 = 2048 + 11 ou mis autrement
2059 1 * 2^11 + 0 * 2^8 + 11 * 2^0 (Note: 2^0 1)

Ainsi pour faire le chemin dans l'autre sens il faut,
[list]
[*] affecter à main le quotient de 2059 par 2048 (2^11) et conserver le reste (appelons-le r1) à part
[*] affecter à middle le quotient de r1 par 256 (2^8) et conserver le reste (appelons-le r2) à part
[*] affecter à sube le quotient de r2 par 1 (2^0), autrement dit r2 est sube
/list

Pour ce faire, tu peux utiliser la fonction Math.DivRem qui permet d'obtenir en résultat le quotient et également le reste à l'aide du paramètre passé ByRef
Je n'ai pas VS sous la main pour certifier d'écrire du code juste mais schématiquement ça devrait ressembler à cela:

Function RecoverAddress(ByVal value As Integer) As String
    'TODO: Rajouter le code de contrôle/vérification
    Dim r1, main, middle, sube As Integer
    main = Math.DivRem(value, 2048, r1)
    middle = Math.DivRem(r1, 256, sube)

    ' pour retrouver le format initial
    Return String.Format("{0}/{1}/{2}", main, middle, sube)
End Function


En espérant ne pas m'être trompé, j'ai fait tout cela de tête
Cordialement !

Merci Sehnsucht 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 97 internautes ce mois-ci

Commenter la réponse de Sehnsucht
Messages postés
15
Date d'inscription
jeudi 21 août 2003
Dernière intervention
4 mars 2011
0
Merci
Tout ca de tête

Vraiment un tout grand merci, ca marche super bien !
Heureusement que le week-end est là, il va falloir en tout ca 2 jours de repos pour digérer la facilité avec la quel tu ma répondu

Bravo et un grand merci.

Kristof
Commenter la réponse de Kristof10
Messages postés
107
Date d'inscription
samedi 25 novembre 2000
Dernière intervention
4 mai 2013
0
Merci
De rien lol, après c'était surtout un problème de maths plus que de code ;)

Juste deux petits chipotages en passant, renvoyer 0 en cas de problème n'est peut-être pas la meilleure chose à faire, après tout rien ne dit que 0 n'est pas valide (d'ailleurs en l'utilisant avec ma méthode, ça ne fait pas planter ça donne juste un résultat bizarre "0/0/0") il vaudrait mieux songer à lancer une exception (par exemple) ou à la limite renvoyer une valeur négative (déjà moins bien à mon gout)

Function NumericAddress(ByVal address As [String]) As Integer
    '...
    If token.Length <> 3 Then Throw New ArgumentException() 'par exemple

    Dim main As Integer = Convert.ToInt32(token(0))
    '...
    End Function


Deuxièmement, évite d'utiliser MsgBox (et autre méthodes uniquement là pour raisons de compatibilité VB6) dans le fond c'est pas dramatique mais ça "fait moins pro" et puis c'est un chouilla moins performant (j'ai dit que c'était du chipotage)

Cordialement !
Commenter la réponse de Sehnsucht
Messages postés
15
Date d'inscription
jeudi 21 août 2003
Dernière intervention
4 mars 2011
0
Merci
Merci pour ces 2 conseils, je vais corriger...

Si tu permets, je vais encore profiter de ton savoir mathématique qui ma laissé.

Voila, je dois faire une fonction qui converti 2 et 78 en binaire. Cela va donner 00000010 01001110. Ensuite je dois séparer E et M comme décrit ici :



E=0000 et M=001001001110.

Ce qui donne après conversion en décimal E=0 et M=590 Ensuite, avec la formule (0.01*M)*2^E donne 5.9.

Le but est de trouvé la valeur 5.9 à partir des chiffres 2 et 78.

Peux-tu m'aider à réaliser cette fonction, ou me mettre su la piste ?

Merci beaucoup de ton aide.

Chrystof
Commenter la réponse de Kristof10
Messages postés
107
Date d'inscription
samedi 25 novembre 2000
Dernière intervention
4 mai 2013
0
Merci
Où se situe exactement ta/tes difficulté(s) si on schématise les étapes:

[list]
[*] Prendre tes deux nombres et les convertir en binaire (donc il faut une fonction qui prend un entier et renvoie un tableau/liste d'entiers, on pourrait renvoyer un string mais le tableau va être utile par la suite)
[*] Normaliser ces tableaux (leur donner une longueur de 8 en rajoutant des 0)
[*] Extraire E et M de ces tableaux (on sait que E c'est le sous tableau de la première valeur d'indices 1 à 4 et M la concaténation du reste)
[*] Reconvertir ces valeurs obtenues en nombre décimaux
[*] Appliquer la formule
/list

Je vais pas rentrer dans le détail des fonctions à écrire, t'aurais plus rien à faire :) mais ça te donne un début de piste, réfléchis-y tente des trucs et si ça coince reviens avec ce que tu auras fait (même faux) on verra à partir de là.

Cordialement !
Commenter la réponse de Sehnsucht
Messages postés
15
Date d'inscription
jeudi 21 août 2003
Dernière intervention
4 mars 2011
0
Merci

[^^confus2][^^confus3][^^confus5][^^choc][^^peur][^^yeuxenlair][^^sad2][^^sad1]
Commenter la réponse de Kristof10
Messages postés
15
Date d'inscription
jeudi 21 août 2003
Dernière intervention
4 mars 2011
0
Merci
Voilà, j'ai fais un bout de code que je vous présente ci-dessous, n'hésitez pas à me corriger, dans tout les cas cela fonctionne...



Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim a, b, ab As String
        a = textToBin(2)
        b = textToBin(78)
        ab = a & b

        Dim sm, se As String
        se = Mid(ab, 2, 4)

        sm = Mid(ab, 1, 1) & Mid(ab, 5, 12)

        '(0.01*M)*2^E
        TextBox2.Text = (0.01 * binToText(sm)) * 2 ^ binToText(se)

    End Sub


 Private Function textToBin(ByVal x As Long) As String
        Dim temp As String
        temp = ""

        Do
            If x Mod 2 Then
                temp = "1" + temp
            Else
                temp = "0" + temp
            End If
            x = x \ 2
            If x < 1 Then Exit Do
        Loop '
        Dim i As Integer
        i = temp.Length
        For j = i To 7
            temp = 0 & temp
        Next
        Return temp
    End Function



Function binToText(ByVal strVal As String) As Single
        Dim i As Integer
        Dim j As Integer
        Dim r As Single
        For i = Len(strVal) To 1 Step -1
            r = r + CInt(Mid(strVal, i, 1)) * 2 ^ j
            j = j + 1
        Next i
        binToText = r
        Return r
    End Function



Merci pour votre aide.

Chrystof
Commenter la réponse de Kristof10
Messages postés
107
Date d'inscription
samedi 25 novembre 2000
Dernière intervention
4 mai 2013
0
Merci
Bon déjà, j'ai envie de dire, youpi ça marche ce qui est déjà l'essentiel.

Maintenant niveau code il y a des choses perfectibles

Déjà le nom des variables, dans la mesure du possible il est plus judicieux de donner un nom qui reflète ce qu'elles contiennent (bon là c'est des histoires de formule donc encore ça peut passer) mais par exemple Button2 et Texbox2 (je sais ça sort du cadre du problème) pourraient se nommer btnExecuteFormula et txtFormulaResult (par exemple) c'est plus clair pour s'y retrouver ensuite ;)

La fonction Mid, est pour moi à proscrire, elle est présente surtout pour des raisons de comptabilité avec VB6 et dans ce cas, la classe String offre des méthodes qui font la même chose (voire souvent de manière plus performante)

D'ailleurs tu es passé par des string au lieu de tableaux et finalement c'est peut-être pas plus mal (comme j'avais pensé le problème dans un autre langage les tableaux étaient mieux adaptés mais pour du VB.Net je pense que j'aurais finalement pris des strings aussi)

Pour la même raison j'avais pensé les fonctions de manière récursive plutôt qu'itérative, dans ce cas-ci les deux se valent donc j'ai rien à dire, enfin...

If x Mod 2 Then
    temp = "1" + temp
Else
    temp = "0" + temp
End If

Ici, si le test est vraie c'est que x Mod 2 renvoie 1 et s'il est faux que x Mod 2 renvoie 0 donc autant écrire:
temp = (x Mod 2) & temp ' à la limite rajouter un .ToString() après la parenthèse


Le If ... Exit Do j'aime clairement pas, autant mettre la condition de sortie sur la boucle Do ... Loop
Do
    '...
Loop Until x = 0 'On boucle jusqu'à ce que x vaille 0


Je peux comprendre que quelqu'un qui débute ait besoin d'étapes mais là, créer un i pour lui mettre la longueur de la chaîne pour l'utiliser dans la boucle (qu'au passage j'aurais séparé dans une autre méthode, si jamais un jour t'as besoin d'une fonction de conversion sans la normalisation t'auras juste à la récupérer, le principe c'est une fonction a une tâche précise; ici convertir en binaire, et elle ne doit faire que cela)

Bon ensuite cette boucle est pas indispensable, la classe String offre une méthode qui te simplifie cette tâche
temp = temp.PadLeft(8, "0"c)

La méthode PadLeft sert à combler à gauche avec des espaces ou le caractère qu'on précise, la notation "0"c c'est pour écrire un caractère car "0" correspond à un String

Après tu as quand même un méli-mélo de tes types, ta fonction textToBin (que j'aurais nommée TextToBin pour respecter les conventions de nommage mais je chipote là) prend un Long en entrée là où tu ne gères que des nombres à 8 bits maximum donc de 0 à 255 donc mettre un Long est peut-être exagéré ^^

Dans binToText tu remet plein de variables pas vraiment utile (enfin j'ai plus d'expérience donc ça fausse le truc) mais surtout non initialisées (j et r) tu as de la chance que par défaut ça prenne 0
Même remarque pour la méthode Len que pour Mid plus haut surtout que dans la fonction d'avant tu utilises temp.Length ??

Pour CInt, c'est du VB.Net et ça fait ce que ça doit, mais (très personnellement) je n'aime pas parce que ça n'existe pas en C#, et comme je jongle souvent de l'un à l'autre je préfère n'utiliser que des choses compatibles ici je pense soit à Convert.ToInt32 (comme dans ton premier post ;) ) soit Int32.Parse

Après il manquerait aussi un peu de vérification (mais ça c'est mon côté perfectionnisme sécuritaire) ^^

Si je résume un peu tout ça voilà ce que j'obtiens (je garde tes noms de variables pour pas te perdre, par contre celle qui me semble "inutiles" je les enlève, en espérant pas te perdre en cours de route)

Private Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button2.Click
    TextBox2.Text = ExecuteFormula(2, 78).ToString()
End Sub

' J'ai hésité puis, finalement j'ai décidé de faire une fonction
' Calculer la fonction Et l'afficher sont deux choses différentes (penser à nommer différemment si cette formule à un meilleur nom)
Private Function ExecuteFormula(ByVal first As Integer, ByVal second As Integer) As Single ' à voir si Single offre suffisamment de précision, sinon utiliser Double ou Decimal
    Dim fstVal, sndVal, eVal, mVal As String

    ' Note si jamais c'est trop d'un coup on peut très bien faire le Normalize ensuite
    ' ex: fstVal = Normalize(fstVal)
    fstVal = Normalize(DecToBin(first))
    sndVal = Normalize(DecToBin(second))

    eVal = fstVal.Substring(1, 4)
    mVal = fstVal(0) & fstVal.Substring(5) & sndVal

    '0.01 * M * 2 ^ E (pas besoin de parenthèses, la priorité opératoire suffit)
    Return = 0.01 * BinToDec(mVal) * 2 ^ BinToDec(eVal)
End Sub

' J'ai décidé de renommer ça en DecToBin, ça reflète mieux ce que ça fait
' Et puis une fonction qui dit transformer du texte en binaire mais qui renvoie du texte c'est bizarre, non ?
Private Function DecToBin(ByVal value As Integer) As String
    ' Je préfère nommer ma variable résultat "result" c'est plus parlant
    ' String.Empty est strictement équivalent à "" c'est juste une préférence perso
    Dim result As String = String.Empty 

    Do
        result = (x Mod 2).ToString() & result
        x \= 2 ' notation raccourcie pour dire x = x \ 2
    Loop Until x = 0

    Return result
End Function

Private Function Normalize(ByVal binaryNumber As String) As String
    Return binaryNumber.PadLeft(8, "0"c)
End Function

' Cette fonction ne peut pas renvoyer de nombre à virgule, Single n'est donc pas justifié ici
Private Function BinToDec(ByVal binaryNumber As String) As Integer
    Dim result, exponent As Integer

    result = 0
    exponent = 0

    ' Ici j'utilise un type de boucle particulier, qui sert à parcourir chaque élément d'une liste/collection
    ' Donc pour un String (qui n'est rien de plus qu'un tableau de caractères) elle parcourra chaque chiffre du nombre binaire
    For Each binDigit In binaryNumber
        result += Int32.Parse(binDigit) * 2 ^ exponent
        exponent += 1
    Next

    Return result
End Function
Commenter la réponse de Sehnsucht
Messages postés
107
Date d'inscription
samedi 25 novembre 2000
Dernière intervention
4 mai 2013
0
Merci
Arf double post, je me suis planté en cliquant sur envoyer au lieu de aperçu

Je voulais juste rajouter que faut pas trop se prendre la tête, j'ai tendance à vouloir rendre parfois les choses "trop parfaites", ton code était bon (faudrait juste se débarrasser de cette habitude d'utiliser les vieilles méthodes VB6, mais ça c'est un problème pour beaucoup de gens qui font du VB.Net par eux-mêmes)

J'espère que je suis pas allé trop loin dans mon truc (qu'au moins tu comprennes ^^) et finalement j'ai fait plus de modif que ce que j'avais dit, bon ya peut-être des boulettes dans le code vu qu'il est parti avant que je puisse relire ^^

Cordialement !
Commenter la réponse de Sehnsucht
Messages postés
107
Date d'inscription
samedi 25 novembre 2000
Dernière intervention
4 mai 2013
0
Merci
Bon ben finalement ça sera un triple-post (je m'en excuse) mais comme j'ai quand même des bonnes boulettes dans le code ça m'embeterait pour l'OP

J'ai finalement ouvert Visual Studio pour être sûr ce coup-ci ^^

Déjà j'ai dû changer le type de résultat de ExecuteFormula de Single à Double sinon j'aurais dû faire une conversion du résultat de Double vers Single (Double est le type par défaut des nombres à virgules), et ça me le signalait comme erreur à cause des paramètres que j'utilise (pas de conversion implicite dans un type qui risquerait de faire perdre de l'information)
Aussi il faut enlever le = Dans le Return et mettre End Function non pas End Sub

Dans DecToBin, j'ai pas fait attention mon paramètre s'appelle value et pas x (merci le copier/coller)

Mais la plus grosse erreur se situe dans BinToDec, en utilisant une boucle for each je ne parcourt plus le nombre "à l'envers" et donc n'utilise pas les bons exposants de puissance de 2 ce qui donne un résultat faux, là j'avais deux choix:

En utilisant la méthode d'extension Reverse applicable aux string, mais selon la version que l'on utilise c'est pas disponible pour tout le monde (au pire il faudrait se l'écrire)
(je pourrais aussi remettre une boucle normale mais j'ai pas envie ^^)
En faisant en sorte d'utiliser le bon exposant, autrement dit en partant d'un exposant maximal et en les diminuant au fur et à mesure que j'avance.
Les exposants vont normalement de 0 jusqu'à la fin de chaine, faisons le contraire ; on connait la longueur de la chaine c'est donc facile:
' Cette fonction ne peut pas renvoyer de nombre à virgule, Single n'est donc pas justifié ici
Private Function BinToDec(ByVal binaryNumber As String) As Integer
    Dim result, exponent As Integer

    result = 0
    exponent = binaryNumber.Length - 1

    ' Ici j'utilise un type de boucle particulier, qui sert à parcourir chaque élément d'une liste/collection
    ' Donc pour un String (qui n'est rien de plus qu'un tableau de caractères) elle parcourra chaque chiffre du nombre binaire
    For Each binDigit In binaryNumber
        result += Int32.Parse(binDigit) * Convert.ToInt32(2 ^ exponent) ' J'ai rajouté une conversion ici pour la même raison évoquée sur ma configuration en début de post
        exponent -= 1
    Next

    Return result
End Function


Bon ce coup-ci ça devrait être bon (sinon je me tire une balle ^^) et encore désolé pour le multi-post

Cordialement !
Commenter la réponse de Sehnsucht
Messages postés
417
Date d'inscription
vendredi 22 février 2008
Dernière intervention
7 janvier 2018
0
Merci
Bonjour a tous les deux,

Voici ma petite contribution a ces PB de conversions

Convert.ToString(Entier, 2) ' 2 pour la base binaire
ex: 4 => "100" en binaire

   
Public Function Convert_Tab_Binaire(ByVal Entier As UInteger) As Boolean()
'Auteur: CGSI3 But: Convertir un UInteger en tableau de binaire 
   Dim binaryVal As String = Convert.ToString(Entier, 2)
   Dim Retour() As Boolean, p As Integer, Cpt As Integer, Cp2 As Integer = binaryVal.Length - 1
   ReDim Retour(Cp2)
      For Cpt = 0 To Cp2
         p = Val(Mid(binaryVal, Cpt + 1, 1))
         Retour(Cp2 - Cpt) (p 1)
      Next Cpt
   Return Retour
End Function


 Public Function MakeShort(ByVal bLow As Byte, ByVal bHigh As Byte) As Short       
'Auteur: CGSI3 But: Retourne un short depuis 2 Bytes 
   Dim Valeur As Byte = 3, Som As Short, by(1) As Byte
   by(0) bHigh : by(1) bLow : Som = BitConverter.ToInt16(by, 0)
   Return Som
End Function


La seconde fonction ne marche pas je veux associer 2 bytes pour fabriquer un short
3 & 0 devrait me donner 15678
Je m'essai a un déchiffreur de fichier binaire:

Plus précisément, en déchiffrant un fichier binaire, voici le nombre que je devrai obtenir, mais je lis un fichier binaire sauvegardé en c
Les données a la lecture du fichier me change beaucoup les choses
3 & 0 ne sont peut être alors pas correct.
Si vous avez une idée,

Et pour finir 3 liens de msdn intéressants

http://msdn.microsoft.com/fr-fr/library/8s62fh68(v=VS.90).aspx
http://msdn.microsoft.com/fr-fr/library/xf983zy2(v=VS.90).aspx
http://msdn.microsoft.com/fr-fr/library/system.bitconverter.toint16.aspx

Bonne journée CGSI3
Commenter la réponse de CGSI3
Messages postés
15
Date d'inscription
jeudi 21 août 2003
Dernière intervention
4 mars 2011
0
Merci
Un grand merci pour votre aide et vos corrections, tout fonctionne à merveille !!!

Kristof
Commenter la réponse de Kristof10
Messages postés
13
Date d'inscription
jeudi 30 août 2001
Dernière intervention
13 novembre 2013
0
Merci
Bonjour,

Merci d'avoir prix le temps de nous aider.
J'ai un peu modifié le code ce qui me permet de m'affranchir des fonctions de conversion

Function DecodeDPT9(ByVal first As Integer, ByVal second As Integer) As Double ' à voir si Single offre suffisamment de précision, sinon utiliser Double ou Decimal
Dim fstVal, sndVal, eVal, mVal As String

fstVal = Normalize(Convert.ToString(first, 2))
sndVal = Normalize(Convert.ToString(second, 2))

eVal = fstVal.Substring(1, 4)
mVal = fstVal(0) & fstVal.Substring(5) & sndVal

Return 0.01 * Convert.ToInt32(mVal, 2) * 2 ^ Convert.ToInt32(eVal, 2)

End Function

Ce code fonctionne parfaitement quand la valeur est positive. Mais quand la valeur est négative le resultat est éronné.

par exemple si j'ai first 135 et second 246, le résultat devrait être -0,3 hors j'ai 40,86. Apparemment il faut utilisé les mantisses??? Pourriez-vous me mettre sur une piste?

Merci
Commenter la réponse de cs_kraven

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.