In che modo posso compiere la semplice operazione:
Non riesco proprio a capire cosa possa essere il problema...codice:(3793882082 And 255)
Grazie
In che modo posso compiere la semplice operazione:
Non riesco proprio a capire cosa possa essere il problema...codice:(3793882082 And 255)
Grazie
... e non usare while wend è una sintassi deprecata
ma il tuo obiettivo qual'è?
credo ke la and funzioni solo su valori booleani...
L'operatore AND non lavora solamente con i valori booleani ma con gli interi, realizzando l'operazione logica AND bit per bit.
Ma i valori devono essere interi e quello indicato eccede il long, che e' l'intero piu' grande utilizzabile in VB.
Dato che la AND e' fondamentalmente equivalente all'operazione modulo, anche se quest'ultimo e' anch'esso utilizzabile solamente con gli interi, si puo' ottenere con semplici operazioni. In particolare, per il valore indicato si ottiene con
Print 3793882082-Int(3793882082/256)*256
che equivale a
Print 3793882082 And 255
oregon ti ringrazio per la risposta con cui sono riuscito a chiarirmi almeno in parte le idee.
Infatti, consultando l'help non avevo molte indicazioni sui limiti della And (come tipologia di parametro avevo "Qualsiasi espressione").
In questo caso posso sostituire la And con l'operazione da te indicata.
Facendo così però riesco a risolvere solo temporaneamente.
Se infatti dovessi affrontare altre operazioni del tipo (ad esempio usando l'operatore Mod) mi ritroverei con valori sempre fuori range.
Il problema quindi è: come posso avere un valore sempre nel campo long (da 00000000 a FFFFFFFF)?
Se infatti eccedo il limite, si genere un errore di Overflow.
Io invece vorrei accaddesse una cosa del tipo:
Graziecodice:Dim n1 As Long Dim n2 As Long n1 = &H87654321 n2 = &H12345678 n1 = n1 * n2 '(n1 = &H70B88D78)
... e non usare while wend è una sintassi deprecata
C'e' qualcosa che non e' chiaro nella tua richiesta.
Quando dici "nel campo long (da 00000000 a FFFFFFFF)" intendi nel campo unsigned long a 32 bit?
Se e' cosi', in VB hai sicuramente delle difficolta' in quanto VB tratta i signed long a 32 bit.
Pero' ci sono dei modi per gestire il problema. A questo punto l'operazione che hai proposto, se non ho capito male
&H87654321 * &H12345678 = &H70B88D78
mi lascia perplesso, dato che il risultato non e' corretto, ne' signed ne' unsigned ...
A questo punto e' meglio che tu spieghi la faccenda ...
Io sapevo che il campo che va da 00000000 a FFFFFFFF è rappresentabile come hai detto tu con o senza segno.
Quindi da 0 a 4294967295 senza segno; da 0 a +2147483647 e da 0 a -2147483647 con segno.
Il problema è che voglio avere un valore sempre a 32 bit.
Il risultato dell'operazione ovviamente eccede questo limite, infatti sarebbe: 693779765864729976 un valore che a 32 bit dovrebbe invece essere 1891143032 cioè 70B88D78.
Ti dico che dovrebbe essere questo perchè provando con la semplice calcolatrice di windows, mi riesce a dare questo valore.
Diciamo che vorrei ottenere un po' quello che accade in assembler con i registri a 32 bit, in cui ad esempio se io incremento il valore FFFFFFFF ottengo 0, senza l'Overflow che lo impedisce.
... e non usare while wend è una sintassi deprecata
Allora ... ricapitoliamo
L'intero piu' grande gestito da VB6 e' il Long che e' interpretato con la regola del complemento a 2 (quindi con segno).
I suoi limiti sono -2147483648 ... +2147483647
Ogni operazione che genera un overflow viene segnalato.
Presumendo che tu non voglia (o possa) usare i floating point per quello che vuoi fare (un single o un double), in VB6 ti devi un po' "arrangiare" sapendo "esattamente" cosa vuoi fare ...
Quindi, se tu vuoi gestire un AND, una moltiplicazione o una addizione con valori interi eccedenti i 32 bit, dovrai valutare 3 tipi di soluzioni diverse per i 3 diversi problemi ...
Oppure implementare del codice assembler all'interno del codice VB per realizzare le operazioni con 32 e piu' bit senza overflow.
A questo punto e' necessario capire "cosa" tu voglia fare in dettaglio ...
Allora, non posso usare i floating point perchè assegnando il risultato ad una variabile di questo tipo diventa impreciso riottenerne il valore a 32 bit e si rischia sempre l'overflow.Originariamente inviato da oregon
Presumendo che tu non voglia (o possa) usare i floating point per quello che vuoi fare (un single o un double), in VB6 ti devi un po' "arrangiare" sapendo "esattamente" cosa vuoi fare ...
Quindi, se tu vuoi gestire un AND, una moltiplicazione o una addizione con valori interi eccedenti i 32 bit, dovrai valutare 3 tipi di soluzioni diverse per i 3 diversi problemi ...
Oppure implementare del codice assembler all'interno del codice VB per realizzare le operazioni con 32 e piu' bit senza overflow.
A questo punto e' necessario capire "cosa" tu voglia fare in dettaglio ...
Penso che come hai detto tu è necessario valutare la soluzione appropriata.
Siccome l'AND ed altri operatori logici funzionano con valori al massimo di 32 bit, la soluzione è risolvere il prodotto a 64 bit così da avere i 32 superiori e i 32 inferiori.
Per la somma infatti, il problema del'overflow non si presenta.
Cosa intendi con implementare codice assembler ?
Io so che non è possibile includerne in VB.
... e non usare while wend è una sintassi deprecata
E chi te lo ha detto? E' possibilissimo invece ...Originariamente inviato da Mabi
Cosa intendi con implementare codice assembler ?
Io so che non è possibile includerne in VB.
Ad esempio, partiamo dalla tua moltiplicazione del cui risultato vuoi la parte a 32 bit meno significativa ...
Parlo dell'operazione
&H87654321 * &H12345678
e della parte di risultato che ti interessa : &H70B88D78
Questo il codice che ho scritto per tale operazione
Fammi saperecodice:Private Declare Function CallWindowProc Lib "user32" _ Alias "CallWindowProcA" (ByVal pLShiftCode As Long, _ ByRef p1 As Long, _ ByVal p2 As Long, _ ByVal p3 As Long, _ ByVal p4 As Long) As Long Dim MulCode() As Byte Dim pMul As Long Private Sub Form_Load() ReDim MulCode(0 To 22) MulCode(0) = &H55 ' push ebp MulCode(1) = &H8B ' mov ebp, esp MulCode(2) = &HEC MulCode(3) = &H57 ' push edi MulCode(4) = &H8B ' mov edi, [ebp+8] MulCode(5) = &H7D MulCode(6) = &H08 MulCode(7) = &H8B ' mov ecx, [ebp+12] MulCode(8) = &H4D MulCode(9) = &H0C MulCode(10) = &H8B ' mov eax, [edi] MulCode(11) = &H07 MulCode(12) = &HF7 ' mul ecx MulCode(13) = &HE1 MulCode(14) = &H89 ' mov [edi], eax MulCode(15) = &H07 MulCode(16) = &H5F ' pop edi MulCode(17) = &H8B ' mov esp, ebp MulCode(18) = &HE5 MulCode(19) = &H5D ' pop ebp MulCode(20) = &HC2 ' ret 16 MulCode(21) = &H10 MulCode(22) = &H00 pMul = VarPtr(MulCode(0)) End Sub Private Sub Command1_Click() Dim VA As Long Dim VB As Long VA = &H12345678 ' Primo valore VB = &H87654321 ' Secondo valore CallWindowProc pMul, VA, VB, 0, 0 Print Hex$(VA) ' Risultato in VA End Sub
Ciao oregon
Scusami per il ritardo nel rispondere.
Il tuo codice è assolutamente ottimo ed è per me un riferimento in quanto ne ero a conoscenza soltanto in minima parte.
Ho provato però a cercare una soluzione alternativa utilizzando quello che c'è in VB e sono a riuscito ad ottentere lo stesso risultato.
Praticamente considero i termini dell'operazione come array di byte e ne eseguo la moltiplicazione trasportando il risultato ancora in un array di byte.
Successivamente riconverto il risultato in un long con segno.
Ad esempio:
Di sicuro è meglio utilizzare la tua soluzione, però mi sono divertito a provare.codice:Private Sub Command1_Click() Dim Numero1(3) As Byte Dim Numero2(3) As Byte Dim Risultato() As Byte Dim RisLong As Long '&H87654321 Numero1(3) = &H87 Numero1(2) = &H65 Numero1(1) = &H43 Numero1(0) = &H21 '&H12345678 Numero2(3) = &H12 Numero2(2) = &H34 Numero2(1) = &H56 Numero2(0) = &H78 Call Moltiplicazione(Numero1, Numero2, Risultato) Call BytesInLong(Risultato, RisLong) '&H70B88D78 MsgBox Hex(RisLong) End Sub Private Sub Moltiplicazione(ByRef Moltiplicando() As Byte, ByRef Moltiplicatore() As Byte, ByRef Prodotto() As Byte) On Error Resume Next Dim Cont1 As Integer Dim Cont2 As Integer Dim ContRiporto As Integer Dim a As Long Dim b As Long Dim c As Long Dim d As Long ReDim Prodotto(0) 'Elimina eventuali byte vuoti 'ad es. 0000AABB = AABB '------------------------------------ Cont1 = UBound(Moltiplicando) Do While (a = 0&) And (Cont1 > 0) a = CLng(Moltiplicando(Cont1)) If (a = 0&) Then ReDim Preserve Moltiplicando(Cont1 - 1) End If Cont1 = (Cont1 - 1) Loop Cont1 = UBound(Moltiplicatore) a = 0& Do While (a = 0&) And (Cont1 > 0) a = CLng(Moltiplicatore(Cont1)) If (a = 0&) Then ReDim Preserve Moltiplicatore(Cont1 - 1) End If Cont1 = (Cont1 - 1) Loop '------------------------------------ For Cont1 = 0 To UBound(Moltiplicando) a = CLng(Moltiplicando(Cont1)) For Cont2 = 0 To UBound(Moltiplicatore) b = CLng(Moltiplicatore(Cont2)) d = a * b If d > 0 Then '--------------------------------------------- ' PRIMO BYTE DEL PRODOTTO '--------------------------------------------- If (Cont1 + Cont2) > UBound(Prodotto) Then ReDim Preserve Prodotto(Cont1 + Cont2) End If c = Prodotto(Cont1 + Cont2) c = c + (d And 255&) Prodotto(Cont1 + Cont2) = CByte((c And 255&)) ' Gestione riporto c = c \ 256& ContRiporto = Cont2 Do While (c > 0&) If (Cont1 + ContRiporto + 1) > UBound(Prodotto) Then ReDim Preserve Prodotto(Cont1 + ContRiporto + 1) End If c = c + CLng(Prodotto(Cont1 + ContRiporto + 1)) Prodotto(Cont1 + ContRiporto + 1) = CByte((c And 255&)) ContRiporto = ContRiporto + 1 c = c \ 256& Loop d = d \ 256& If d > 0 Then '--------------------------------------------- ' SECONDO BYTE DEL PRODOTTO '--------------------------------------------- If (Cont1 + Cont2 + 1) > UBound(Prodotto) Then ReDim Preserve Prodotto(Cont1 + Cont2 + 1) End If c = CLng(Prodotto(Cont1 + Cont2 + 1)) c = c + (d And 255&) Prodotto(Cont1 + Cont2 + 1) = CByte((c And 255&)) ' Gestione riporto c = c \ 256& ContRiporto = Cont2 Do While (c > 0&) If (Cont1 + ContRiporto + 2) > UBound(Prodotto) Then ReDim Preserve Prodotto(Cont1 + ContRiporto + 2) End If c = c + CLng(Prodotto(Cont1 + ContRiporto + 2)) Prodotto(Cont1 + ContRiporto + 2) = CByte((c And 255&)) ContRiporto = ContRiporto + 1 c = c \ 256& Loop End If End If Next Cont2 Next Cont1 End Sub Private Sub BytesInLong(ByRef ArrByte() As Byte, ByRef Var As Long) On Error Resume Next Dim Cont As Integer Dim Num As Integer Dim Massimo As Integer Massimo = UBound(ArrByte) If UBound(ArrByte) > 3 Then Massimo = 3 End If If Massimo < 3 Then Var = 0 For Cont = 0 To Massimo Var = Var + (ArrByte(Cont) * (256 ^ Cont)) Next Cont Else If ArrByte(3) < 128 Then Var = 0 For Cont = 0 To Massimo Var = Var + (ArrByte(Cont) * (256 ^ Cont)) Next Cont Else Var = 0 For Cont = 0 To Massimo If Cont = 0 Then Num = 256 - ArrByte(Cont) Else Num = 255 - ArrByte(Cont) End If Var = Var + (Num * (256 ^ Cont)) Next Cont Var = Var * -1 End If End If End Sub
Grazie![]()
... e non usare while wend è una sintassi deprecata