Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

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
556
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…