Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Logical Operations on Currency 1

Status
Not open for further replies.

HughLerwill

Programmer
Nov 22, 2004
1,818
GB
I'm trying to simulate logical AND and OR on Currency variables. So far I have the code below but it is not quite working e.g. CurrencyAND(1,3) is returning 0.9488 instead of 1; CurrencyOR(1,3) is returning 3.0512 rather than 3.
Could be I have a couple of the Hi/Los reversed or is it more complicated?

Code:
'ref [URL unfurl="true"]http://support.microsoft.com/kb/189862[/URL]
'jan 2013
Private Type MungeCurr
    Value As Currency
End Type

Private Type Munge2Long
    LoValue As Long
    HiValue As Long
End Type

Public Function CurrencyAND(C1 As Currency, C2 As Currency) As Currency

    Dim Lo1&, Hi1&, Lo2&, Hi2&
    CurrencyToTwoLongs C1, Lo1, Hi1
    CurrencyToTwoLongs C2, Lo2, Hi2
    
    Dim RetLo&, RetHi&
    RetLo& = Lo1 And Lo2
    RetHi& = Hi1 And Hi2
    CurrencyAND = TwoLongsToCurrency(RetLo&, RetHi&)

End Function

Public Function CurrencyOR(C1 As Currency, C2 As Currency) As Currency

    Dim Lo1&, Hi1&, Lo2&, Hi2&
    CurrencyToTwoLongs C1, Lo1, Hi1
    CurrencyToTwoLongs C2, Lo2, Hi2
    
    Dim RetLo&, RetHi&
    RetLo& = Lo1 Or Lo2
    RetHi& = Hi1 Or Hi2
    CurrencyOR = TwoLongsToCurrency(RetLo&, RetHi&)

End Function

Private Function TwoLongsToCurrency(Long1, Long2) As Currency
'ref [URL unfurl="true"]http://support.microsoft.com/kb/189862[/URL]
    Dim C As MungeCurr, L As Munge2Long
    L.HiValue = Long1
    L.LoValue = Long2
    LSet C = L
    TwoLongsToCurrency = C.Value

End Function

Private Sub CurrencyToTwoLongs(MyC As Currency, Long1, Long2)
'ref [URL unfurl="true"]http://support.microsoft.com/kb/189862[/URL]
    Dim C As MungeCurr, L As Munge2Long
    C.Value = MyC
    LSet L = C
    Long1 = L.HiValue
    Long2 = L.LoValue

End Sub
 
Firstly, why are you trying to simulate when it works directly?


Secondly
>Could be I have a couple of the Hi/Los reversed or is it more complicated?
yes, it is more complicated. Currency is basically an integer scaled by 10000.

What you are effectively doing is:

msgbox ((1 * 10000) OR (3 * 10000))/10000
msgbox ((1 * 10000) AND (3 * 10000))/10000

The 64bit maths tricks the Microsoft illustrate work fine for the normal maths operations because the scaling has no impact:

msgbox ((1 * 10000) + (3 * 10000))/10000



 
So you can 'fix' your simulation as follows:

Public Function CurrencyAND(C1 As Currency, C2 As Currency) As Currency

Dim Lo1&, Hi1&, Lo2&, Hi2&
CurrencyToTwoLongs C1 / 10000, Lo1, Hi1
CurrencyToTwoLongs C2 / 10000, Lo2, Hi2

Dim RetLo&, RetHi&
RetLo& = Lo1 And Lo2
RetHi& = Hi1 And Hi2
CurrencyAND = TwoLongsToCurrency(RetLo&, RetHi&) * 10000

End Function

Public Function CurrencyOR(C1 As Currency, C2 As Currency) As Currency

Dim Lo1&, Hi1&, Lo2&, Hi2&
CurrencyToTwoLongs C1 / 10000, Lo1, Hi1
CurrencyToTwoLongs C2 / 10000, Lo2, Hi2

Dim RetLo&, RetHi&
RetLo& = Lo1 Or Lo2
RetHi& = Hi1 Or Hi2
CurrencyOR = TwoLongsToCurrency(RetLo&, RetHi&) * 10000

End Function



 
stongm - many thanks for that, I thought I was close, you saved me half a day.

>why are you trying to simulate when it works directly?
Because it does'nt work directly on values > 2^30.
Intended use is on a variable in which I need to store more than 30 attributes/ bits of data.
 
But that's a slightly different issue. And removing the scaling as my 'fix' does (and you'll now appreciate why I deliberately put that in quotes) will lose you bits.

You don't actually care what the value of Currency is, you only care about the underlying bit pattern. And in that case, the results you got previously are correct, because you are not actually doing

1 OR 3 (i.e. 00000001 OR 00000011)

You are ORing the bit pattern that represents 1 in a Currency variable with the bit pattern that represents 3. The bit pattern you get back is correct, just not what you (incorrectly) expect. If you see what I mean.

 
Yes I notice that I'm limited to 49 bits which is just fine/ working well in my current application.
However it would be nice to squeeze out a as many usable bits as possible, so it there a way to retrieve a few more without changing the basic calls. I guess these are the bits which the Currency Type normally uses to store its decimal portion.
 
You should be able to use all 64 bits, you just CANNOT at the same time try and use the Currency variable AS Currency. Just treat it as a black box, and read and write it through the support functions CurrencyToTwoLongs and TwoLongsToCurrency.

But the question then becomes: do you really need currency at all? For example, a userdefined type could be equally useful:

Private Type ManyBits
ByteBits(1 To 8) As Byte
End Type
 
I'm getting an Error 404 on the paperclip in your last post but I can see where you are coming from. Thanks again for your help.
 
I have no idea what that paperclip represents. Certainly nothing I entered ... and examining the source for this page agrees - the link is blank. Most odd.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top