|
-
Oct 15th, 2024, 05:20 AM
#1
Thread Starter
Fanatic Member
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
-
Oct 15th, 2024, 05:29 AM
#2
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".
-
Oct 15th, 2024, 05:35 AM
#3
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
-
Oct 15th, 2024, 05:41 AM
#4
Thread Starter
Fanatic Member
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
-
Oct 15th, 2024, 09:57 AM
#5
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.
-
Oct 15th, 2024, 10:11 AM
#6
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.
-
Oct 15th, 2024, 11:51 AM
#7
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
-
Oct 15th, 2024, 01:46 PM
#8
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.
-
Oct 15th, 2024, 02:35 PM
#9
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
-
Oct 16th, 2024, 07:51 AM
#10
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|