Newsgroup: it.comp.lang.visual-basic
Titolo: Somma senza overflow?

Qualcuno sa/si ricorda come sommare due Long tra di loro ed ottenere 
sempre e comunque un Long, non generando un errore di overflow in caso 
di risultato superiore al limite massimo del tipo Long? E possibilmente 
(ma se non c'è altro modo mi adeguerò) senza usare funzioni esterne e 
variabili temporanee di tipo Currency?
E' abbastanza importante, sto riscrivendo l'oggetto Collection (e varie 
altre strutture dati indicizzate tramite stringhe) e questo tipo di 
operazione mi serve per il calcolo degli hash delle chiavi :(

 operazione mi serve per il calcolo degli hash delle chiavi :(
So che sarà come spararmi sui piedi, ma hai già dato un occhio alla classe
XCollection sul Sito Comune (Leonardo)?
Ciao
-- SiDB Simple DataBase engine ---------------------------
 
http://space.virgilio.it/zntf...@tin.it/sidb/sidb.htm
----------------------------------------------------------

variabili temporanee di tipo Currency?
Se uso i Decimal va bene lo stesso ? :-PPP
Sfruttando una funzione che avevo pubblicato sul ng questa estate,
ti abbozzo quest' idea.
Ti prego di informarmi sui miglioramenti che riuscirai a fare ;-)
ciao, hal
-------------------------------------------
Public Function FuckOverflow(ByVal a As Long, b As Long) As Long
    FuckOverflow = CLng("&H" & Right$(GetHex(CStr(CDec(a) + CDec(b))), 8))
End Function
Public Function GetHex(ByVal a_BigNumber As String) As String
 
    Dim mi_Num As Variant
    Dim mi_Div As Variant
 
    '// converte nel sottotipo Decimal
    mi_Num = CDec(a_BigNumber)
    mi_Div = CDec(0)
 
    Do
        mi_Div = (mi_Num / 16)
 
        '// previene l' overflow nell' uso di Mod (funziona solo con i Long)
        If (mi_Num > &H7FFFFFFF) Then
            GetHex = Hex$((mi_Div - Int(mi_Div)) * 16) & GetHex
        Else
            GetHex = Hex$(mi_Num Mod 16) & GetHex
        End If
        mi_Num = Int(mi_Div)
    Loop While mi_Num > 0
 
End Function    '// GetHex
Public Sub Test()
    Dim ret As Long
    ret = FuckOverflow(&H5F123456, &H4F678901)
    Debug.Print ret, Hex$(ret)
End Sub

 writes:
K:H> Qualcuno sa/si ricorda come sommare due Long tra di loro ed ottenere 
K:H> sempre e comunque un Long, non generando un errore di overflow in caso 
K:H> di risultato superiore al limite massimo del tipo Long?
Loop sui vari bit del long facendo un XOR tra i bit corrispondenti degli
addendi e l'eventuale carry (a zero per il 1^ bit).
Pensandoci  un po'  su è  probabilmente possibile  "parallelizzare" le
operazioni sui bit...
Alla peggio rivolgiti all'assembler...
--
Gian Uberto| main(){printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Lauri      |                        David Korn, 1987 ioccc best one liner 
(aka saint)|-------------------------------------------------------------------
em@ail: 
sa...@eng.it
 ( vedere X-nospam nello header - see X-nospam in header )

(Leonardo)?
Che strutture usi internamente? (comunque lo scarico e gli do' 
un'occhiata, sono curioso :)

Ti prego di informarmi sui miglioramenti che riuscirai a fare ;-)
intravvedo un pesantissimo uso di funzioni stringa, fortunatamente 
quest'accrocco mi serve unicamente nell'IDE... (nel compilato finale 
funziona tutto alla perfezione usando direttamente gli operatori, a 
patto di disattivare il controllo dell'overflow, cosa che mi accingo a 
fare definitivamente creando un _default.vbp apposito...). E' un peccato 
comunque avere un progetto frenato e uno completamente bloccato per un 
dettaglio cosě stupido :/
[...]
Grazie, ci darň un'occhiata... tu perň da' un'occhiata alla mia Mul(), 
chissŕ che non riesci a scoprire l'errore misterioso ;)

End Function
Aggiornamento: la Sum funziona, la Mul, scritta allo stesso identico 
modo, no. Provatela anche voi, ditemi quanto vi da' Mul(&HFFFFFFFF, 
&HFFFFFFFF). Se vi da' 1, voi siete fortunati e io sono finito :) perchè 
non riesco a capire dove sia il problema. Se vi da' altri pittoreschi 
valori, allora c'è proprio qualcosa che non va:
Function Mul(ByVal dwX As Long, ByVal dwY As Long) As Long
  Dim dwlTemp1 As Currency, dwlTemp2 As Currency
  CopyMemory dwlTemp1, dwX, LenB(dwX)
  CopyMemory dwlTemp2, dwY, LenB(dwY)
  Let dwlTemp1 = dwlTemp1 * dwlTemp2
  CopyMemory Mul, dwlTemp1, LenB(Mul)
End Function
(occhio che i primi due parametri della dichiarazione di CopyMemory che 
uso io sono ByRef As Any)

 non riesco a capire dove sia il problema
In effetti la tua Mul č molto folkloristica :)
Prova cosě:
Private Declare Function MulDiv Lib "kernel32" (ByVal nNumber As Long, ByVal
nNumerator As Long, ByVal nDenominator As Long) As Long
Private Sub Command1_Click()
    Dim n1 As Long
    Dim n2 As Long
    Dim n3 As Long
    n1 = &HFFFFFFFF
    n2 = &HFFFFFFFF
    n3 = MulDiv(n1, n2, 1&)
    Debug.Print n3
End Sub
Purtroppo ha delle limitazioni nei valori restituiti (secondo me piuttosto
idiote), perň potrebbe bastarti.
In alternativa prova con Int32x32To64(), dovrebbe funzionare (non provato)
se il valore finisce in un currency e poi lo moltiplichi per 10000.
Ciao

chissà che non riesci a scoprire l'errore misterioso ;)
Tentar non cuoce ...
ciao, hal

In alternativa prova con Int32x32To64(),
E' definita come una macro :( Come dire, se usate il C, bene, sennò 
v'attaccate al tram :(

 v'attaccate al tram :(
E' vero, non avevo visto...
Allora io userei la forza bruta a questo punto.
Ti scrivi una dll in C con la tua Mul(), Div(), Plus(), Minus(), Fuckus()...
Ci metti 5 minuti.
Ciao