IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Division Euclidienne en Binaire


Sujet :

Macros et VBA Excel

  1. #1
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2017
    Messages : 11
    Points : 12
    Points
    12
    Par défaut Division Euclidienne en Binaire
    Salut !

    SVP je cherche un code (vba de préférence pour aller dans mes macros excel)
    permettant de faire la division binaire de 2 "mots" binaires, et prenant en entrée des string.

    Ex: Function Division_Binaire(byval S1 as string, byval S2 as string) as String

    Le but c'est de connaitre le reste de la division euclidienne d'une chaîne binaire par une autre.

    Je suis quasi certain qu'un code aussi basique que çà a déjà été produit, mais mes aptitudes en vba sont limitées,
    et je ne voudrais pas prendre des heures (voire des jours) à rentrer dans la programmation de ce truc s'il existe déjà.

    J'ai beau chercher depuis quelques bonnes heures déjà et je ne trouve toujours rien.
    J'espère que qqn ici aura qqch à me proposer.

    Merci infiniment de votre assistance, j'ai vraiment besoin de ce truc pour avancer sur mon projet

    @+

  2. #2
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Bonjour
    Le plus simple est probablement de transposer les deux en décimal, de calculer ce reste (modulo) à re-transposer en binaire.

    Et donc : simple formule Excel utilisant les fonctions BINDEC, DECBIN et MOD
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2017
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par unparia Voir le message
    Bonjour
    Le plus simple est probablement de transposer les deux en décimal, de calculer ce reste (modulo) à re-transposer en binaire.
    Merci beaucoup Unparia !

    Oui j'avais effectivement vu cette possibilité, mais le traitement doit se faire sans conversion, donc avec les mots binaires directement.
    Et ceci pour 3 raisons:
    _ La 1ère c'est que la fonction mod (a;b) sous vba ne fonctionne pas avec les GRANDS nombres (limités au type double en vba)
    _ La seconde, c'est que pour des nombres TRES GRANDS (==> donc on ne peut même plus utiliser le type double)
    on ne peut s'en sortir qu'en manipulant les nombres au travers de leur représentation en string
    _ La troisième, est que pour des nombres TRES TRES GRANDS, la durée d'exécution pour les opérations de conversion
    binaire-->décimal et décimal-->binaire est très très long

    En conséquence, pas d'autres choix que de faire toutes les opérations avec les nombres l'on connait déjà dans leur représentation binaire
    stockée comme une string.

    Merci encore d'avoir bien voulu m'aider.

    @+

  4. #4
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Bien.

    Il s'agit donc, avant tout développement en code, d'établir l'algorithme nécessaire (à traduire ENSUITE en code).
    Quel est donc le tien (algo classique ou en langage naturel) ?
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2017
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par unparia Voir le message
    Bien.

    Il s'agit donc, avant tout développement en code, d'établir l'algorithme nécessaire (à traduire ENSUITE en code).
    Quel est donc le tien (algo classique ou en langage naturel) ?

    Merci encore à toi Unparia pour l'intérêt et le temps que tu consacres à ma question.

    En fait dans mes recherches voici le genre d'algorithme que j'ai trouvé: https://sitelec.org/cours/abati/division_binaire.htm


    Mais avant de me lancer dans des heures de programmation, je cherche si quelque chose d'utilisable n'est pas déjà produit.

    En vba excel de préférence (sinon, même si c'est en C, je ferai l'effort de le re-écrire en vba plutôt que de partir de zéro
    avec toutes les possibilités de me tromper dans le source à développer ....)

    Merci

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 2 267
    Points : 3 663
    Points
    3 663
    Par défaut
    Bonjour à tous,

    La troisième, est que pour des nombres TRES TRES GRANDS, la durée d'exécution pour les opérations de conversion
    binaire-->décimal et décimal-->binaire est très très long
    C'est vrai qu'avec des Strings c'est mieux ;-)

    Plaisanterie mise à part si 28 chiffres te suffisent tu as CDec()
    Pris sur feu Excelabo :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Function MOD2(Nombre As String, Diviseur As String) As String
    Dim Tmp
    Tmp = CDec(Nombre) / Diviseur
    MOD2 = Nombre - CDec(Left(Tmp, InStr(1, Tmp, _
    Application.International(xlDecimalSeparator)) - 1)) * Diviseur
    End Function
    Et si tu es destiné à devoir faire ta fonction tout seul, met-toi plutôt en quête d'un algorithme de division traitant par tranches.
    Par tranche de 16 bits par exemple, plutôt que bit à bit.
    eric

  7. #7
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2017
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Bonjour Eric !

    Merci vraiment pour ta réponse.
    Tu ris de moi en disant : "C'est vrai qu'avec des string c'est mieux"
    mais je t'assure qu'il n'y a pas d'autre moyen que de passer par des string ou des tableaux de caractères.
    Je ne t'en veux pas pour ce tacle hyper léger , c'est permis au foot, l’arbitre ne siffle même pas

    Plaisanterie mise à part, 28 chiffres ne me suffisent absolument pas!
    C'est même ridicule comparé à la taille des mots binaires que je manipule.
    En l'occurrence je travaille sur de grands nombres pouvant comporter plusieurs centaines de milliers de chiffres !!!

    La vérité c'est qu'il n'y a aucun moyen de représenter des chiffres qui dépassent le type double
    (dont la limite est 308 chiffres) autrement qu'en les prenant comme des string,
    et ensuite de faire voltiger toutes ces strings à notre guise un peu comme dans un bar à strip-tease .
    Càd faire toutes sortes de traitements (basés sur les opérations classiques: addition, soustraction, multiplication, division, etc... ) en fonction de l'objectif visé: ici modulo.

    Mais j'ai eu (la nuit portant conseil), l'idée de les traiter mes mots binaires par tranches de 10.000 chiffres, ce qui rejoint l'idée que tu proposes à la fin.
    Merci encore ! Je vais donc m'y atteler!
    Il va bien falloir que je mette la main au cambouis hélas. Je ne voulais pas écrire du code, mais je me rends compte que je passe plus de temps à chercher ce bout de code que de l'écrire moi-même

    @+

  8. #8
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 947
    Points : 4 058
    Points
    4 058
    Par défaut
    Bonjour.
    je travaille en ce moment sur ce genre de problème pour le Crible Quadratique.
    Où là aussi il faut manipuler des nombres de plusieurs milliers de chiffres.
    Pour les opérations classiques il y a ce site : http://fordom.free.fr/
    Le modulo est un autre problème, je n'ai rien trouvé et j'ai dû développer moi même "DGN" pour compléter les fonctions existantes :
    je suis preneur si tu trouves une solution plus rapide :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    Option Explicit
     
    '---------------------------------------------------------------------------------------
    Public Function DGN(ByVal vcChiffre As String, _
                        ByVal Diviseur As Variant, _
                        Optional ByRef Reste As Variant, _
                        Optional ByVal Précision As Integer = 0) As Variant
    '---------------------------------------------------------------------------------------
    ' Division de vcChiffre (Entier Positif ou Négatif) par Diviseur (Entier Positif ou Négatif).
    ' Retourne : le Quotient d'un grand nombre si AvecVirgule=False,
    '          : la division avec une précision jusqu'à de 28 chiffres si Précision>0.
    ' Renseigne : Reste = le reste sous la forme d'un entier grand nombre.
    '---------------------------------------------------------------------------------------
    Dim N As Long
    Dim Quotient As Variant, Dividende As Variant
    Dim Q As String
    Dim Signe As String
     
    If Left(vcChiffre, 1) = "-" And Left(Diviseur, 1) <> "-" Then Signe = "-"
    If Left(vcChiffre, 1) <> "-" And Left(Diviseur, 1) = "-" Then Signe = "-"
     
    vcChiffre = AbsGN(vcChiffre)
    Diviseur = AbsGN(Diviseur)
     
    Select Case Len(Diviseur)
     
        ' Si le diviseur est petit:
        Case Is <= 27
     
            ' Si le chiffre est lui aussi petit:
            If Len(vcChiffre) <= 27 Then
     
                DGN = CDec(Int(CDec(vcChiffre) / CDec(Diviseur)))
                Reste = MOD2(vcChiffre, Diviseur)
     
            ' Sinon le chiffre est grand (mais le diviseur est petit):
            Else
     
                N = 27
                Dividende = Mid(vcChiffre, 1, N)
                Quotient = Int(CDec(Dividende) / CDec(Diviseur))
                Reste = CDec(Dividende) - CDec(Quotient * Diviseur)
                Q = CStr(Quotient)
     
                While N < Len(vcChiffre)
                    N = N + 1
                    Dividende = CDec(Reste) & Mid(vcChiffre, N, 1)
                    Quotient = Int(CDec(Dividende) / CDec(Diviseur))
                    Q = Q & Quotient
                    Reste = CDec(Dividende) - CDec(Quotient * Diviseur)
                Wend
     
                ' Boucle de recherche des zéros inutiles dans la partie entière
                For N = 1 To Len(Q)
                    If Mid$(Q, N, 1) <> "0" Then Exit For
                Next N
                Q = Mid$(Q, N)
                If Q = vbNullString Then Q = "0" ' Cas d'un nombre nul
     
                DGN = Q
     
            End If
     
        ' Dans les autres cas le diviseur est grand (et le chiffre surement aussi):
        Case Else
     
            DGN = DivGN(vcChiffre, Diviseur, Reste)
     
    End Select
     
    ' S'il faut retourner un nombre avec virgule et pas un entier:
    If Précision > 0 Then
        Dim v As Variant, a As Variant, b As Variant, i As Integer
        a = CDec(Mid(Reste, 1, 27))
        b = CDec(Mid(Diviseur, 1, 27))
        If Len(Diviseur) > 27 Then i = Len(Diviseur) - 27
        If Len(Reste) > 27 Then i = i - (Len(Reste) - 27)
        If i > 0 And i <= 27 Then a = a / (10 ^ i)
        If i > 27 Then a = 0
        v = Round(a / b, Précision)
        DGN = AGN(DGN, v)
    End If
     
    ' Gestion des signes négatifs:
    DGN = Signe & DGN
     
    End Function
     
    '-------------------------------------------------------------------------------
    Private Function DivGN(ByVal vcChiffre As String, ByVal Diviseur As String, _
                           Optional ByRef Reste As Variant) As Variant
    '-------------------------------------------------------------------------------
    ' Division d'un grand nombre entier positif par un diviseur entier positif.
    ' Méthode inspirée de cette discussion:
    ' https://www.developpez.net/forums/d1019631/bases-donnees/ms-sql-server/developpement/probleme-utilisation-modulo/#post5686484
    ' Retourne : le Quotient d'un grand nombre vcChiffre divisé par Diviseur.
    ' Renseigne : Reste = le reste sous la forme d'un entier grand nombre.
    '-------------------------------------------------------------------------------
    Dim iIndice As Long, iTemporaire As String
    Dim Div As String
    Reste = ""
     
    While Len(vcChiffre) > 0
        iIndice = Len(vcChiffre) Mod 10
        If iIndice = 0 Then iIndice = 10
        iTemporaire = AGN(Reste & "0000000000", Val(Mid(vcChiffre, 1, iIndice)))
        vcChiffre = Mid(vcChiffre, iIndice + 1, Len(vcChiffre) - iIndice)
        Div = Div & DivLog2GN(iTemporaire, Diviseur, Reste, "0000000000")
    Wend
     
    ' Supprime les zéros inutiles au début du chiffre:
    iIndice = 1
    While Mid$(Div, iIndice, 1) = "0"
        iIndice = iIndice + 1
    Wend
     
    ' Retourne la division:
    DivGN = Mid$(Div, iIndice)
    If DivGN = "" Then DivGN = "0" ' Cas d'un nombre nul
    End Function
     
    '-------------------------------------------------------------------------------
    Private Function DivLog2GN(ByVal vcChiffre As String, ByVal Diviseur As String, _
                               Optional ByRef Reste As Variant, _
                               Optional ByRef FormatZéro As Variant = "") As Variant
    '-------------------------------------------------------------------------------
    ' Utilise les logarithmes pour faire une division d'un grand nommbre.
    ' Retourne : le Quotient d'un grand nombre vcChiffre divisé par Diviseur.
    ' Renseigne : Reste = le reste sous la forme d'un entier grand nombre.
    '-------------------------------------------------------------------------------
    Dim Q As Variant, QQ As String
    Dim Début As String, Fin As String, Div As String
     
    ' Si le dividende est plus petit que le diviseur
    ' alors retourne 0 et le dividende est le reste:
    If CompGNrapide(vcChiffre, Diviseur) < 0 Then
        DivLog2GN = 0
        Reste = vcChiffre
        Exit Function
    End If
     
    QQ = vcChiffre
    Div = "0"
     
    ' Une division est une soustraction de log(dividende) - log(diviseur):
    ' Ce qui donne un "minima" puisque le log n'est pas toujours assez précis.
    ' Ce minima + 1 donne le maxima et maxima fois diviseur doit être inférieur
    ' au dividende, dans ce cas la division est trouvée,
    ' sinon il faut reprendre avec la partie représentant l'écart entre le dividende
    ' et le minima fois le diviseur. Et ainsi de suite.
    Do
     
        Q = LogGN(QQ) - LogGN(Diviseur)
        Q = CDec(Q)
        Début = PuissanceGN("2,718281828459", Int(Q))
        Début = PGN(Début, Exp(Q - Int(Q)))
        Début = IntGN(Début)
     
        Div = AGN(Div, Début)
        QQ = AGN(vcChiffre, "-" & PGN(Div, Diviseur))
     
        Fin = AGN(Div, "1")
     
    Loop While CompGNrapide(PGN(Fin, Diviseur), vcChiffre) < 1
     
    Reste = QQ
     
    ' Si le reste est négatif c'est qu'il y a une erreur,
    ' le diviseur est trop grand et il faut le diminuer:
    While Left(Reste, 1) = "-"
        Div = AGN(Div, "-1")
        Reste = AGN(vcChiffre, "-" & PGN(Div, Diviseur))
    Wend
     
    DivLog2GN = Format(Div, FormatZéro)
     
    End Function
     
    '-------------------------------------------------------------------------------
    Public Function LogGN(ByVal vcChiffre As String) As Variant
    '-------------------------------------------------------------------------------
    ' Retourne le Log2 d'un grand nombre Entier Positif.
    ' En VBA log() est limité à 10^308, donc au dela il faut calculer soit même le log.
    '-------------------------------------------------------------------------------
    Dim Chiffre As Variant
    Chiffre = Left(vcChiffre, 1) & "." & Mid(vcChiffre, 2, 12)
    Chiffre = Val(Chiffre)
    If Len(vcChiffre) < 300 Then
        LogGN = Log(Chiffre) + Log(10 ^ (Len(vcChiffre) - 1))
    Else
        LogGN = Log(Chiffre) + ((Len(vcChiffre) - 1) * 2.30258509299405)
    End If
    End Function
     
    '-------------------------------------------------------------------------------
    Public Function SqrGN(ByVal a As String, Optional ByVal Précision As Byte = 10) As String
    '-------------------------------------------------------------------------------
    ' Retourne la racine carrée (approximative) d'un grand nombre Entier Positif.
    ' Inspiré de l'algorithme d'HÉRON.
    '-------------------------------------------------------------------------------
    ' Limite de la précision à 10 décimale:
    If Précision > 10 Then Précision = 10
     
    ' Si la racine peut être calculée alors la retourner:
    If Len(a) <= 15 Then SqrGN = Round(Sqr(CDec(a)), Précision): Exit Function
     
    ' Sinon il faut la calculer:
    Dim x1, x2, x0, i As Byte
    x1 = a
     
    For i = 1 To 250
        x2 = DGN(a, IntGN(AGN(x1, x1)), 0, 0)
        x1 = AGN(PGN(x1, "0.5"), x2)
        If x1 = x0 Then Exit For
        If x1 < 1 Then Exit For
        x0 = x1
    Next i
     
    ' Arrondi à l'entier le plus proche:
    x1 = ArrondiGN(x1, 0)
     
    ' Traitement pour rechercher les décimales:
    If Précision > 0 Then
        x0 = AGN(a, "-" & PGN(x1, x1))  ' Calcule l'écart du carré par rapport au nombre.
        x2 = "0"
        While x0 <> x2
            x2 = x0
            x0 = DGN(x0, a, 0, 28)          ' En déduit le pourcentage.
            If x0 > 0 And x0 < 1 Then
                x0 = SqrPN(CDec(1) + CDec(x0))  ' Calcule la racine carrée précise sur un petit nombre.
                x1 = PGN(x1, x0)                ' Ajoute la racine carré du pourcentage calculé.
                x0 = AGN(a, "-" & PGN(x1, x1))  ' Calcule l'écart du carré par rapport au nombre.
            Else
                x2 = x0 ' Force la sortie de la boucle.
            End If
        Wend
    End If
     
    SqrGN = ArrondiGN(x1, Précision)
    End Function
     
    '-------------------------------------------------------------------------------
    Private Function SqrPN(a As Variant) As Variant
    '-------------------------------------------------------------------------------
    ' Calcule la racine carrée d'un petit nombre de façon plus précise que la formule VBA.
    '-------------------------------------------------------------------------------
    Dim i As Byte, x0, x1
    x1 = a
    For i = 1 To 250
        x1 = x1 * 0.5 + (CDec(a) / (CDec(2) * CDec(x1)))
        If x1 = x0 Then Exit For
        x0 = x1
    Next i
    SqrPN = x1
    End Function
     
    '-------------------------------------------------------------------------------
    Public Function RacineGN(ByVal vcChiffre As String) As String
    '-------------------------------------------------------------------------------
    ' Retourne la racine carrée très approximative d'un grand nombre Entier Positif.
    ' Mais ça suffit dans notre cas.
    '-------------------------------------------------------------------------------
    Dim Chiffre As Variant
    Chiffre = Left(vcChiffre, 1) & "." & Mid(vcChiffre, 2, 12)
    Chiffre = Val(Chiffre)
    RacineGN = PuissanceGN(Sqr(10), Len(vcChiffre) - 1)
    RacineGN = PGN(RacineGN, Sqr(CDec(Chiffre)))
    End Function
     
    '-------------------------------------------------------------------------------
    Public Function ModGN(ByVal vcChiffre As String, ByVal Diviseur As String) As Variant
    '-------------------------------------------------------------------------------
    ' Retourne le modulo d'un grand nombre.
    '-------------------------------------------------------------------------------
    Call DGN(vcChiffre, Diviseur, ModGN)
    End Function
     
    '---------------------------------------------------------------------------------------
    Public Function CompGNrapide(ByVal b As String, ByVal a As String) As Long
    '---------------------------------------------------------------------------------------
    ' Fait une comparaison des deux grands nombres par contrôle de cohérence pour gagner
    ' du temps. Si ce n'est pas possible alors lance la fonction standard CompGN().
    '---------------------------------------------------------------------------------------
    ' Retourne : 1 si le premier nombre > le deuxième nombre
    '           -1 si le premier nombre < le deuxième nombre
    '            0 si les deux nombres sont égaux.
    '---------------------------------------------------------------------------------------
    If Left(b, 1) = "-" And Left(a, 1) <> "-" Then
        CompGNrapide = -1
    ElseIf a = b Then
        CompGNrapide = 0
    Else
        Select Case Len(b)
            Case Is > Len(a): CompGNrapide = 1
            Case Is < Len(a): CompGNrapide = -1
            Case Else: CompGNrapide = CompGN(b, a)
        End Select
    End If
    End Function
     
    '---------------------------------------------------------------------------------------
    Public Function PgcdGN(ByVal a As String, ByVal b As String) As String
    '---------------------------------------------------------------------------------------
    ' Calcul le PGCD de deux grands nombres
    ' Variante optimisant l'Algo d'Euclide
    '---------------------------------------------------------------------------------------
     
    ' Si la taille de a et b est petite alors utilise la fonction Pgcd2 qui est plus rapide:
    If Len(a) <= 28 And Len(b) <= 28 Then
        PgcdGN = Pgcd2(CDec(a), CDec(b))
        Exit Function
    End If
     
    ' Déclarations:
    Dim R As String
     
    ' Validité paramètre:
    a = AbsGN(a)
    b = AbsGN(b)
    If CompGN(a, b) = -1 Then R = b: b = a: a = R 'inverse les valeurs
     
    ' Calcul:
    Do While CompGNrapide(AbsGN(b), "1") >= 0
        R = ModGN(a, b)
        a = b
        b = R
    Loop
    PgcdGN = AbsGN(a)
    End Function
    '---------------------------------------------------------------------------------------
    '---------------------------------------------------------------------------------------

  9. #9
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2017
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par laurent_ott Voir le message
    Bonjour.
    je travaille en ce moment sur ce genre de problème pour le Crible Quadratique.
    Où là aussi il faut manipuler des nombres de plusieurs milliers de chiffres.
    Pour les opérations classiques il y a ce site : http://fordom.free.fr/
    Le modulo est un autre problème, je n'ai rien trouvé et j'ai dû développer moi même "DGN" pour compléter les fonctions existantes :
    je suis preneur si tu trouves une solution plus rapide :
    Salut Laurent !
    Merci à toi pour ton assistance et tes conseils.
    En fait j'avais déjà le zip complet de fordom qui est vraiment excellent (je rends ici vivement hommage à son développeur), mais limité comme tu as pu le constater.
    Les opérations classiques d'addition de grands nombres, soustraction (addition signée), multiplication, etc... fonctionnent bien, mais la fonction division n'y est pas développée, pas plus que la fonction ModuloGN. Il y a bien un MOD2 qui n'est d'ailleurs pas mis dans le module calculs_GN, mais dans le module fonction_sur_les_nombres, ..., et pour cause !
    En fait ce MOD2 sert juste à repousser la limite du MOD classique de excel/vba du type long au type double.

    Et merci aussi pour le code que tu me proposes. Je vais l'essayer pour voir s'il comble mes besoins.

    En fait je ne sais même plus si je vais continuer avec les string!
    En faisant des tests de performance, je réalise que traiter les grands nombres comme des tableaux est hautement plus efficace que comme des string.
    Fais le test et tu verras, la différence est phénoménale !!! Notamment l'accès à un chiffre du nombre par Tableau(i) et mille fois plus rapide que par Mid(Chaîne, i) lorsqu'il s'agit de très grands nombres.
    Et quand tu mets tout cela dans une boucle qui doit itérer sur la longueur du nombre, tu peux te retrouver avec une performance de 7 secondes dans un cas contre 30 minutes dans l'autre !!!

    Merci encore !

    La connaissance augmente lorsqu'elle est partagée !

  10. #10
    Expert éminent sénior Avatar de Menhir
    Homme Profil pro
    Ingénieur
    Inscrit en
    Juin 2007
    Messages
    16 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 16 037
    Points : 32 866
    Points
    32 866
    Par défaut
    Peut-être devrais-tu songer à t'orienter vers des logiciels plus orientés math comme MatLab.
    https://excel.developpez.com/cours/?...omation#Matlab
    https://www.developpez.net/forums/f1...pement/matlab/
    https://matlab.developpez.com/tutoriels/
    Ou une de ses alternatives gratuites comme R, FreeMat, etc.
    Merci de cliquer sur pour chaque message ayant aidé puis sur pour clore cette discussion.

  11. #11
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Juste une petite question de débutant qui lit :
    En l'occurrence je travaille sur de grands nombres pouvant comporter plusieurs centaines de milliers de chiffres !!!
    Dans quel type de variable texte comptes-tu donc mettre tout cela (de surcroît en représentation binaire) ?
    Le type string de vba ne me parait pas de nature à y faire face, lui ....
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

  12. #12
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 947
    Points : 4 058
    Points
    4 058
    Par défaut
    Bonjour.
    Si j'ai bien compris, Black Confucius travaille sur des grands nombres (plusieurs milliers de chiffres) et dispose pour les opérations classiques des fonctions de fordom qui traitent les nombres au format String (de mémoire un string peut faire environ 2 millions de caractères).
    Son problème est qu'il n'y a pas dans le pack des fonctions proposées une fonction pour les divisions et donc pour le calcul du modulo.
    J'ai aussi rencontré ce problème et j'ai développé une fonction personnelle, DGN (voir plus haut, attention il faut avoir téléchargé les fonctions de fordom pour que ça marche).
    Cette fonction utilise aussi le format String pour les nombres. Ça marche bien, mais ça prend du temps : par exemple une division d'un nombre de 100 000 chiffres par un nombre de 10 000 chiffre demande 1 minute.
    Il y a donc peut-être un algorithme plus rapide pour faire tout cela ?
    Si vous en connaissez un je suis preneur.
    Peut-être faut-il utiliser les tableaux au lieu des String ? Je ne sais pas.

    Quant aux langages de substitution proposés, ils posent le problème de ne pas être compatibles avec un développement en VBA.
    Et peut importe la raison, bonne ou mauvaise, de Black Confucius de vouloir utiliser absolument le VBA même s'il n'est pas fait pour cela. Le but est de trouver une réponse (en VBA) à son problème.

    Je reste curieux des avancées faites par Black Confucius sur ses recherches et j'espère qu'il nous donnera des retours.
    Bonne programmation.

  13. #13
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Bonjour laurent_ott

    Je pense à un truc arithmétique qui consiste à traiter le dividende par tranches de 9 de gauche à droite et de remplacer, pour chaque tranche, le dividende par le modulo de la tranche par le diviseur. En utilisant l'opérateur Mod de VB.
    Cela serait à mon avis possible, mais à condition que le diviseur soit, lui, typé en numérique inférieur à 100 000 000 (le dividende étant lui en string).
    Si cela t'intéresse, je peux probablement écrire un petit bout de code en exemple de mécanisme ******. Je ne sais pas s'il est possible/envisageable de s'inspirer d'un tel mécanisme.

    EDIT : ******. Je viens à l'instant d'écrire le mécanisme. A toi de me dire s'il convient que tu voies ce code (qu'il te faudra adapter en ce qui concerne l'aspect diviseur).
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

  14. #14
    Expert éminent sénior Avatar de Menhir
    Homme Profil pro
    Ingénieur
    Inscrit en
    Juin 2007
    Messages
    16 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 16 037
    Points : 32 866
    Points
    32 866
    Par défaut
    Citation Envoyé par laurent_ott Voir le message
    format String (de mémoire un string peut faire environ 2 millions de caractères).
    En fait, c'est environ 2 milliards (à condition que la RAM tienne le coup).
    Mais uniquement si c'est une variable String de longueur fixe, c'est-à-dire qui est définie à sa déclaration et qui ne change plus.
    Pour une variable classique de longueur variable, on tombe à environ 65 536 caractères max.

    De loin le type de données le plus gourmand en mémoire qu'on puisse utiliser en VBA.
    Merci de cliquer sur pour chaque message ayant aidé puis sur pour clore cette discussion.

  15. #15
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 947
    Points : 4 058
    Points
    4 058
    Par défaut
    Citation Envoyé par unparia Voir le message
    Bonjour laurent_ott

    Je pense à un truc arithmétique qui consiste à traiter le dividende par tranches de 9 de gauche à droite et de remplacer, pour chaque tranche, le dividende par le modulo de la tranche par le diviseur. En utilisant l'opérateur Mod de VB.
    A toi de me dire s'il convient que tu voies ce code (qu'il te faudra adapter en ce qui concerne l'aspect diviseur).
    Bonjour unparia.
    Oui je veux bien voir ce que cela donne, par curiosité, et ça peut donner des idées, et être utilisé dans d'autres cas que le mien car je travaille plus avec les divisions qu'avec les modulo dans le cadre du crible quadratique (où le diviseur est souvent petit, j'ai donc une fonction optimisée pour ce cas mais ce n'est pas le sujet ici).
    Je ne te promets pas une réponse rapide car il faut que je trouve un peu de temps.
    Et il faut que je compare sa rapidité avec ma fonction.

    Je ne sais pas si cela répond au besoin de Black Confucius qui est resté un peu vague sur ses attentes et ses contraintes.
    En tout cas, merci pour ton implication.

  16. #16
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Alors voilà, mis en code, le mécanisme dont il s'agit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Dim nb As String, Diviseur As Long
      nb = String(60000, "8") ' -->> est une longue chaîne de "8" (60000 "8")
      Diviseur = 1547302
      deb = Timer
      While Len(nb) > 9
        nb = CStr(Val(Left(nb, 9) Mod Diviseur)) & Mid(nb, 10)
      Wend
      nb = CStr(Val(nb Mod Diviseur))
      MsgBox Timer - deb & "seconds --->>" & vbCrLf & nb
    Tu n'as pas besoin de prendre la peine de me répondre.
    Ou tu peux t'en inspirer et tant mieux, ou tel n'est pas le cas et tant pis.
    cela ne regarde que toi.
    Amitiés.
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

  17. #17
    Invité
    Invité(e)
    Par défaut
    Bonsoir,
    En fait j'ai rien compris!

    Tu cherche a faire un modulo d'un nombre a x milier de digit par y milier de digit

    X mod y ou alors x mod 10.

    String mod 97 par exemple c'est très facile.

    Donnes des précisions sur les deux terme.

  18. #18
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2017
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Bonsoir Laurent, Unparia, Menhir, Eric, ... !

    Et merci encore pour vos suggestions. En fait je travaille sur la recherche de nombres premiers jumeaux, et nombres premiers sexy où la question de recherche de diviseurs ou facteurs est centrale, donc scribe (scribe basé sur Ératosthène, scribe quadratique, autre ...) et opération modulo.

    Vous avez tous souligné les soucis que je rencontre.

    • Sur le problème du stockage des variables, il n'y a aucun type en vba (et dans tout autre langage ou environnement) qui permette de contenir un nombre comportant des milliers voire des millions de chiffres. Donc l'astuce (ou plutôt une des astuces ...) pour traiter de tels grands nombres c'est de passer par des string, puisque la taille maximale d'une string est 2^31 (soit 2.147.483.648 caractères). Donc si chaque chiffre de notre grand nombre représente un caractère de notre string, on pourrait en théorie traiter de cette sorte des nombres pouvant aller jusqu'à plus de 2 milliards de chiffres.
    • Ensuite vient le problème de performance. Comme l'a si bien mentionné Laurent, c'est gourmand en temps d'exécution de parcourir une string de cette taille pour faire des opérations sur chacun des caractères qui le composent, que ce soit des caractères 'décimaux' ou 'binaires'! Et c'est gourmand en mémoire aussi: j'ai planté déjà 2 fois mon ordinateur en m'approchant de nombres à 1 million de chiffres. C'est la raison pour laquelle j'ai pensé à utiliser des tableaux (également limités à 2^31 cases) plutôt que des string, car traitement beaucoup plus optimisé aussi bien en temps d'exécution qu'en mémoire utilisée. Je vais donc hélas devoir me passer des fonctions GN de fordom, ou re-écrire celles dont j'ai besoin en version tableau et non plus string. Si j'y parviens, je reprendrai volontiers ce que tu as produit Laurent, le faire en version tableau, et te le rebalancer.
    • L'autre aspect que vous avez souligné, c'est la question "pourquoi vba"? Bah je suis plutôt de la vielle école et je suis plus à l'aise avec çà, bien que je sache pertinemment qu'il y a mieux!

    Citation Envoyé par laurent_ott Voir le message
    Cette fonction utilise aussi le format String pour les nombres. Ça marche bien, mais ça prend du temps : par exemple une division d'un nombre de 100 000 chiffres par un nombre de 10 000 chiffre demande 1 minute.
    Il y a donc peut-être un algorithme plus rapide pour faire tout cela ?
    Si vous en connaissez un je suis preneur.
    Peut-être faut-il utiliser les tableaux au lieu des String ? Je ne sais pas.
    Je retourne d'abord vérifier et compléter mes connaissances en arithmétique modulaire. Il y a certainement des possibilités d'optimiser les temps de calculs en prenant des tailles raisonnables dans notre "mot", et par propagation, utilisant les propriétés de la fonction modulo, faire un traitement récursif qui puisse mener au résultat souhaité en un temps raisonnable.

    Merci encore à vous tous !
    @+

  19. #19
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2017
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par unparia Voir le message
    Alors voilà, mis en code, le mécanisme dont il s'agit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Dim nb As String, Diviseur As Long
      nb = String(60000, "8") ' -->> est une longue chaîne de "8" (60000 "8")
      Diviseur = 1547302
      deb = Timer
      While Len(nb) > 9
        nb = CStr(Val(Left(nb, 9) Mod Diviseur)) & Mid(nb, 10)
      Wend
      nb = CStr(Val(nb Mod Diviseur))
      MsgBox Timer - deb & "seconds --->>" & vbCrLf & nb
    Tu n'as pas besoin de prendre la peine de me répondre.
    Ou tu peux t'en inspirer et tant mieux, ou tel n'est pas le cas et tant pis.
    cela ne regarde que toi.
    Amitiés.
    Merci encore!
    Verdict:
    4 secondes pour 100.000 chiffres.
    29 minutes pour 1 million de chiffres.
    Donc réponse à Laurent, tu pourras prendre ce code si les performances ci-dessus sont meilleures que ce que tu obtiens!
    Pour ma part, je n'ose même pas essayer 10 millions de chiffres
    MERCI beaucoup tout de même Unparia, c'est vraiment sympa!

  20. #20
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 82
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 422
    Points
    12 422
    Par défaut
    Bonjour Black Confucius

    J'ai donc compris que tu t'étais "lancé" dans la recherche du plus grand nombre premier supérieur au record actuel (que détient, si ma mémoire ne me trompe pas, un ressortissant indien... mais n'en suis pas certain)

    J'appelle à tout hasard ton attention sur le fait que la détermination rigoureuse du modulo (si nul dans les divisions successives par des premiers déjà connus -->> nb non premier) n'est pas indispensable.

    Je ne vais pas développer ce mécanisme, mais t'en soumettre la pensée à tout hasard -->>

    Qu'est le "déroulement" d'une division de type scolaire (donc par traitement d'un dividende et d'un diviseur exprimé sous forme de chaînes de caractères), sinon la détermination, par tranches décalées du nombre de soustractions du diviseur tant que la tranche traitée lui est supérieure ? Et quand devenue inférieure, on "décale" de 1 ce qui reste de la tranche en lui ajoutant le caractère suivant du dividende.
    On sait que le modulo est différent de 0 si, in fine (lorsque plus de décalage possible), le diviseur est supérieur au résultat de la dernière soustraction alors que ce résultat est différent de 0.
    Nous n'avons pas besoin d'en calculer la valeur puisqu'il suffit de déterminer si elle est >= 0

    Bon courage (tu t'es lancé dans un sacré défi, si tu cherches à battre le record actuel)
    Je n'accepte pas de demande d' "amitié" individuelle. Tout développeur est pour moi un ami.
    Je n'ouvre AUCUN classeur tiers (avec ou sans macro ******). Ne m'en proposez donc pas .

    ****** : Non, non ... un classeur .xlsx ne "peut" par exemple et entre autres pas contenir un activex (de surcroît invisible) , "bien sûr" ...

    Il est illusoire de penser que l'on saurait exprimer valablement et précisément en un langage (rigide) de développement ce que l'on peine à exprimer dans le langage naturel, bien plus souple.

Discussions similaires

  1. dépacement capacité (division euclidienne)
    Par Darksnakes dans le forum Débuter
    Réponses: 5
    Dernier message: 01/12/2008, 09h20
  2. Division euclidienne
    Par cixiii dans le forum R
    Réponses: 1
    Dernier message: 24/04/2008, 18h02
  3. Division euclidienne polynomiale (avec modulos)
    Par Batoche dans le forum Mathématiques
    Réponses: 5
    Dernier message: 18/12/2006, 14h03
  4. division euclidienne de polynôme
    Par gronaze dans le forum Mathématiques
    Réponses: 1
    Dernier message: 29/06/2006, 20h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo