XL 2016 Calcul

Dudu2

XLDnaute Barbatruc
Bonjour,
Comment identifier que l'une quelconque de ces valeurs est présente dans une somme quelconque de ces mêmes valeurs suite de puissances de 2 ?
1
2
4
8
16
32
64
128
256

Par exemple dans la somme 97 il y a 1 + 32 + 64.
Donc (97 modulo 2) = 1 => 1 est présent

Bon finalement j'ai une solution, mais si vous en avez une ça m'intéresse aussi
Merci par avance.
 
Dernière édition:
Solution
VB:
Sub Lister()
Dim X&
   X = 9379
 
  MsgBox X & " = " & ListPuiss2Rd$(X&)
End Sub

Function ListPuiss2Rd$(ByVal Somme2n&)
 i = 1: T = ""
While i < Somme2n&
If (Somme2n& And i) = i Then
    If T <> "" Then T = T & " + "
          T = T & i
End If
i = i * 2 'i valeur du Bit 1,2,4,8 etc.
Wend
ListPuiss2Rd$ = T
End Function

Dudu2

XLDnaute Barbatruc
Bonjour @mapomme,
Voili voilou...
VB:
Sub Test()
    Const k = 2 ^ 0 + _
              2 ^ 3 + _
              2 ^ 4 + _
              2 ^ 6 + _
              2 ^ 7
          
    MsgBox PuissanceDe2PrésentEnValeur(2 ^ 4, k)
End Sub

Function PuissanceDe2PrésentEnValeur(PuissanceDe2 As Long, SommeDePuissancesDe2 As Long) As Boolean
    Dim i As Integer
    Dim q As Long
 
    Const MaxPuissanceDe2 = 10
 
    q = SommeDePuissancesDe2
    For i = 0 To MaxPuissanceDe2
        If q Mod 2 ^ (i + 1) = 2 ^ i Then
            If 2 ^ i = PuissanceDe2 Then Exit For
            q = q - 2 ^ i
        End If
    Next i
 
    'Return value
    If i <= MaxPuissanceDe2 Then
        PuissanceDe2PrésentEnValeur = True
    End If
End Function

Edit: modifié le nom de la fonction pour éviter un anglicisme.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Dans le même genre sur le même algorithme, la liste des puissances de 2 d'une somme de puissances de 2.
VB:
Sub Test2()
    Const k = 2 ^ 0 + _
              2 ^ 3 + _
              2 ^ 4 + _
              2 ^ 6 + _
              2 ^ 7
             
    Call ListeDesPuissancesDe2(k)
End Sub

Sub ListeDesPuissancesDe2(SommeDePuissancesDe2 As Long)
    Dim i As Integer
    Dim q As Long
    Dim p As Long
    Dim S As String
   
    Const MaxPuissanceDe2 = 10
   
    q = SommeDePuissancesDe2
    For i = 0 To MaxPuissanceDe2
        If q Mod 2 ^ (i + 1) = 2 ^ i Then
            If Len(S) > 0 Then
                S = S & " + "
            End If
            S = S & CStr(2 ^ i)
            p = p + 2 ^ i
            q = q - 2 ^ i
        End If
    Next i
   
    If p <> SommeDePuissancesDe2 Then
        MsgBox "Gros bug !"
    Else
        MsgBox "PuissanceDe2 = " & SommeDePuissancesDe2 & " (" & S & ")"
    End If
End Sub
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Re,

Allez pour le fun!


VB:
Function JenSuis(ByVal Puiss2&, ByVal Somme2n&) As Boolean
Dim max&, x&, i&
   max = 1 + Int(Log(Somme2n) / Log(2)): If 2 ^ max > Somme2n Then max = max - 1
   For i = max To 0 Step -1
      x = 2 ^ i
      If x <= Somme2n Then
         If x = Puiss2 Then
            JenSuis = True: Exit Function
         Else
            If x <= Somme2n Then Somme2n = Somme2n - x
         End If
      End If
   Next i
End Function
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Re,

Pour la liste (et toujours pour le fun) :
VB:
Sub Lister()
Dim X&
   X = 9379
   MsgBox Join(Array(X, Replace(ListPuiss2(X), " ", " + ")), " = ")
End Sub

Function ListPuiss2$(ByVal Somme2n&)
Dim max&, X&, i&, s$
   If Somme2n <= 0 Then Exit Function
   max = 1 + Int(Log(Somme2n) / Log(2)): If 2 ^ max > Somme2n Then max = max - 1
   For i = max To 0 Step -1
      X = 2 ^ i
      If X <= Somme2n Then s = X & " " & s: Somme2n = Somme2n - X
   Next i
   ListPuiss2 = Trim(s)
End Function
 

dysorthographie

XLDnaute Accro
Bonjour,
Je suis pas certaine d'avoir compris, mais selon moi il faut récupérer les valeurs de Bits a 1 de la valeur binaire.
Dim i as integer ,v as integer,t as string
Code:
V= 97: i=256: t=""
While i=>1
If v And i=I then
    If t<>"" then t=t & " +"
          T=t & l
End if
I=i/2
Wend
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Merci pour vos réponses intéressantes.
Alors @mapomme, ta solution j'y ai aussi pensé en déjeunant, car dans le sens de la descente la soustraction est effectivement plus simple (vu que la somme de tous les 2**n est toujours inférieure à 2**n+1), mais j'apprécie ton calcul du Max de matheux qui m'échappe.

@dysorthographie, en effet, un And sur les bits c'est tout à fait judicieux.
 

dysorthographie

XLDnaute Accro
VB:
Sub Lister()
Dim X&
   X = 9379
 
  MsgBox X & " = " & ListPuiss2Rd$(X&)
End Sub

Function ListPuiss2Rd$(ByVal Somme2n&)
 i = 1: T = ""
While i < Somme2n&
If (Somme2n& And i) = i Then
    If T <> "" Then T = T & " + "
          T = T & i
End If
i = i * 2 'i valeur du Bit 1,2,4,8 etc.
Wend
ListPuiss2Rd$ = T
End Function
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonsoir à @Dudu2, @dysorthographie ;),

Une généralisation à une puissance N quelconque.

Pour la liste des composant de la somme, une fonction à deux ou trois paramètres :

Function ListeSommePuissanceN( Somme, N, optional exposant ) avec
  • Somme : la somme des puissances de N
  • N : la puissance à considérer
  • Le troisième paramètre (s'il est présent) renvoie une chaine avec les exposants de N qui composent la somme

Pour savoir si un nombre X est membre des composants de la somme, une fonction à trois paramètres :

Function JenSuis(Nombre, N, Somme) avec
  • Nombre : le nombre à chercher dans les composants de la Somme
  • N : la puissance à considérer
  • Somme : la somme des puissances de N
VB:
Public Function ListeSommePuissanceN$(ByVal Somme&, ByVal N&, Optional exposant)
Dim max&, X&, i&, s$
   If Somme <= 0 Or N <= 1 Then Exit Function
   max = 1 + Int(Log(Somme) / Log(N)): If N ^ max > Somme Then max = max - 1
   For i = max To 0 Step -1
      X = N ^ i
      If X <= Somme Then
         If IsMissing(exposant) Then s = X & " " & s Else s = N & "^" & i & " " & s
         Somme = Somme - X
      End If
   Next i
   If Somme = 0 Then ListeSommePuissanceN = Trim(s) Else ListeSommePuissanceN = "?"
End Function

Function JenSuis(ByVal Nombre&, ByVal N&, ByVal Somme&) As Boolean
   JenSuis = InStr(ListeSommePuissanceN(Somme, N), " " & Nombre & " ") > 0
End Function
 

Pièces jointes

  • dudu2- somme de puiss de N- v1.xlsm
    20.6 KB · Affichages: 3

Dudu2

XLDnaute Barbatruc
Concernant le calcul du Max un Int(Log(Somme) / Log(n)) devrait suffire.
Tant que Somme est défini en Long.

Avec Somme défini en Double, il y a des aberrations qui apparaissent dans les calculs.
On peut avoir:
- Log(Somme) / Log(n) = 15
- Int(Log(Somme) / Log(n)) = 14
- Int(CDbl(Log(Somme) / Log(n))) = 14


Ou encore:
- Log(Somme) / Log(n) = 25
- Int(Log(Somme) / Log(n)) = 24
- Int(CDbl(Log(Somme) / Log(n))) = 25


Donc ton calcul:
Max = 1 + Int(Log(Somme) / Log(n)): If n ^ max > Somme Then Max = Max - 1
protège parfaitement de ces dérapages connus.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Ou alors une alternative qui semble fonctionner:
Max = Application.RoundDown(Log(Somme) / Log(n), 0)
Code:
Sub a()
    Dim Max As Long
    Dim Somme As Double
    Dim n As Integer

    n = 3
    
    Somme = n ^ 0 + _
            n ^ 1 + _
            n ^ 2 + _
            n ^ 3 + _
            n ^ 4
            
    Somme = n ^ 15
    
    Max = 1 + Int(Log(Somme) / Log(n))
    If n ^ Max > Somme Then Max = Max - 1
    
    MsgBox "Brut = " & Log(Somme) / Log(n) & vbCrLf & _
           "Int() = " & Int(Log(Somme) / Log(n)) & vbCrLf & _
           "Int(Cdbl()) = " & Int(CDbl(Log(Somme) / Log(n))) & vbCrLf & _
           "RoundDown() = " & Application.RoundDown(Log(Somme) / Log(n), 0) & vbCrLf & _
           "Max = " & Max
End Sub
 

Discussions similaires

Réponses
5
Affichages
532

Statistiques des forums

Discussions
312 215
Messages
2 086 330
Membres
103 187
dernier inscrit
ebenhamel