Results 1 to 10 of 10

Thread: How do I avoid overflow while using currency?

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2017
    Posts
    761

    Question How do I avoid overflow while using currency?

    Hello!

    I need to copy a big file (over 2 gb).
    I am distributing this work over several activex exes of which each copies a "chunk".

    I am having a problem distributing the work over them as I encounter an overflow error, no matter what I try.
    I used modulo and int.

    Can somebody advise me how to solve this?

    Thank you.

    Here is my prototype function:

    Code:
    Private Sub Form_Load()
    
        Dim lCountWorkers&
        Dim cBytesToBeCopiedByEach As Currency
        
        Dim cFileSize As Currency
        cFileSize = 2247442432#
        
        
        CalculateNumberOfWorkersAndWork cFileSize, 6, lCountWorkers, cBytesToBeCopiedByEach
    
    End Sub
    Public Sub CalculateNumberOfWorkersAndWork(ByVal uFileSize As Currency, ByVal uMaxWorkers As Long, ByRef uCountWorkers As Long, ByRef uBytesToBeCopiedByEach As Currency)
    
        'My code is really crappy. I have tried a lot. This version is just a mockup to show you what I want to do
        'I am not even sure if this approach would yield the correct result even if it would not throw the overflow error
        uBytesToBeCopiedByEach = uFileSize / uMaxWorkers
        
    
        Dim wholeParts As Currency
        wholeParts = uFileSize \ uMaxWorkers
    
        Dim totalWholePartSize As Currency
        totalWholePartSize = wholeParts * uMaxWorkers
    
    
        If totalWholePartSize = uFileSize Then
            uCountWorkers = uMaxWorkers
        Else
            uCountWorkers = wholeParts + 1
        End If
    
        If uFileSize < uMaxWorkers Then
            uCountWorkers = uFileSize
            uBytesToBeCopiedByEach = 1
        End If
    
    End Sub
    This one as well throws an overflow error

  2. #2
    PowerPoster VanGoghGaming's Avatar
    Join Date
    Jan 2020
    Location
    Eve Online - Mining, Missions & Market Trading!
    Posts
    2,622

    Lightbulb Re: How do I avoid overflow while using currency?

    The \ operator does integer division and works only with "Long" variables. Replace it with "Int(x / y)" to replicate its behavior for numbers larger than "Long".

  3. #3
    PowerPoster VanGoghGaming's Avatar
    Join Date
    Jan 2020
    Location
    Eve Online - Mining, Missions & Market Trading!
    Posts
    2,622

    Lightbulb Re: How do I avoid overflow while using currency?

    You can also replace "Mod" with this function that works with larger numbers (including "Decimal"):

    Code:
    Public Function BigMod(vDividend As Variant, vDivisor As Variant) As Variant
        BigMod = vDividend - Int(vDividend / vDivisor) * vDivisor
    End Function

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2017
    Posts
    761

    Re: How do I avoid overflow while using currency?

    Edit: I have now tried RC6, but since I am math noob I have no idea if that is correct:

    Code:
        Dim lCountWorkers&
        Dim cBytesToBeCopiedByEach As RC6.cBigInt
    
        Dim cFileSize As Currency
        cFileSize = 2247442432#
        
        Set cBytesToBeCopiedByEach = New_c.BigInt
        
        CalculateNumberOfWorkersAndWork uFileSize, 6, lCountWorkers, cBytesToBeCopiedByEach
    
    Public Sub CalculateNumberOfWorkersAndWork(ByVal uFileSize As Currency, ByVal uMaxWorkers As Long, ByRef uCountWorkers As Long, ByRef uBytesToBeCopiedByEach As cBigInt)
    
        Dim cFileSize As cBigInt
        Set cFileSize = New_c.BigInt
        cFileSize.InitFromString CStr(uFileSize)
    
        Dim remainingBytes As cBigInt
        Set remainingBytes = New_c.BigInt
        
        Set uBytesToBeCopiedByEach = cFileSize.DivInt(uMaxWorkers)
        Set remainingBytes = cFileSize.ModInt(uMaxWorkers)
        
        uCountWorkers = uMaxWorkers
        
        Dim s$
        s = remainingBytes.ToString
        If s <> "0" Then
            uCountWorkers = Fix(cFileSize.DivBig(uBytesToBeCopiedByEach))
            Dim sMod$
            sMod = cFileSize.ModBig(uBytesToBeCopiedByEach).ToString
            
            If sMod <> "0" Then
                uCountWorkers = uCountWorkers + 1
            End If
        End If
        
    If cFileSize.CompInt(uMaxWorkers) < 0 Then
            uCountWorkers = cFileSize.ToString
            uBytesToBeCopiedByEach.InitFromString "0"
        End If
    End Sub

  5. #5
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: How do I avoid overflow while using currency?

    Yeah, math with any kind of "integer" can get a bit tricky and confusing.

    Here is some code that hopefully clears a bit of it up:

    Code:
    Option Explicit
    
    Private Sub Form_Load()
        Dim c1 As Currency
        Dim c2 As Currency
        
        c1 = 5
        c2 = 6
        
        Debug.Print TypeName(c1 \ c2)       ' Reports "Long"
        Debug.Print TypeName(c1 / c2)       ' Reports "Double"
        Debug.Print TypeName(c1 Mod c2)     ' Reports "Long"
        
        ' So, how do we divide these currencies?
        ' One "safe" way is to:
        
        Debug.Print TypeName(CDec(c1) / CDec(c2))   ' Reports "Decimal"
        
        ' Since a "Decimal" type completely covers the range of a Currency,
        ' it's safe to go:
        
        Dim c3 As Currency
        c3 = CDec(c1) / CDec(c2)
        
        
    
    
    End Sub
    If you truly want a MOD for Currency, that's a bit of different problem, and I don't believe VanGogh's approach will work for all possible values of Currency.

    @VanGogh, I didn't test, but what if vDividend is near the max of a Currency, and vDivisor = 0.0001? That internal division should fail. Doing a MOD on floating point numbers is a bit unusual, but not unheard of. (One place I frequently use it is when dealing with degrees, or radians).
    Last edited by Elroy; Oct 15th, 2024 at 10:04 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: How do I avoid overflow while using currency?

    A simple (although possibly not the speediest) way to do a Currency MOD is something like the following:

    Code:
    Public Function CurMod(c1 As Currency, c2 As Currency) As Currency
        CurMod = c1
        Do While CurMod > c2: CurMod = CurMod - c2: Loop
    End Function
    And this won't overflow (unless it's truly overflowing the Currency type, such as a huge negative C2).
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  7. #7
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,294

    Re: How do I avoid overflow while using currency?

    if you dont mind using a c dll you can use unsigned types including 64 bit numbers and math operations w/ overflow wrapping

    http://sandsprite.com/tools.php?id=31

  8. #8
    PowerPoster VanGoghGaming's Avatar
    Join Date
    Jan 2020
    Location
    Eve Online - Mining, Missions & Market Trading!
    Posts
    2,622

    Re: How do I avoid overflow while using currency?

    The very definition of a remainder (MOD) implies integer operands. The function takes variant parameters especially to accommodate the biggest possible integers (Decimal type). Other than that I don't know what else can you ask of it.

  9. #9
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: How do I avoid overflow while using currency?

    Code:
    Option Explicit
    
    Private Declare Function RtlLargeIntegerDivide Lib "ntdll" ( _
                             ByVal cA As Currency, _
                             ByVal cB As Currency, _
                             Optional ByRef cR As Currency) As Currency
    
    Private Sub Form_Load()
        Dim cRemainder  As Currency
        
        ' // Currency is int64 / 10000
        ' // Calc 1234123424124 / 100 = 12341234241
        Debug.Print RtlLargeIntegerDivide(123412342.4124@, 0.01@)   ' //  1234123,4241 [ok]
        ' // Calc 1234123424124 mod 100 = 24
        RtlLargeIntegerDivide 123412342.4124@, 0.01@, cRemainder    ' //   0,0024 [ok]
        Debug.Print cRemainder
        
    End Sub

  10. #10
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: How do I avoid overflow while using currency?

    AI (Gemini):

    Can a MOD operator be performed on floating point numbers?

    Yes, the MOD operator can be performed on floating-point numbers.

    While it's primarily used for integers to find the remainder after division, many programming languages extend its functionality to floating-point numbers. The result is the remainder of the floating-point division.
    That's pretty much exactly the gist of what I originally said.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width