Hy, i try to integrate a code that validates bank account and i need to work with very long numbers. Ex.: 1010101011131007593840000272444 / 97. I defined a variable as LON, as DOUBLE... but i'm getting OVERFLOW. How can i correct this ??? Thanx in advance !!!
Double can't hold 31 digits: Debug.Print Format$(CDbl("1010101011131007593840000272444"), "0")
1010101011131010000000000000000
Floating point datatype simply drops anything it can't hold, but remembers the position of the decimal separator. What this means is Double should never be used with money.
VB6 has two datatypes that would be good for money: Currency & Variant's Decimal subtype. Neither of these can hold 31 digits, however 1010101011131007593840000272444 is far more money than anyone has in their bank account.
I would say Currency is good enough for pretty much any need you have, it is 64-bit "hacked" Integer designed for dealing with money. It can hold values between -922337203685477.5807 and 922337203685477.5807 [smallest negative = -0.0001, smallest positive = 0.0001].
Decimal subtype of Variant can hold even bigger than that, it holds 97 bits for pure Integer math (96 bits unsigned Integer + 1 bit for positive or negative indicator), but it also allows floating point style positioning of the decimal separator.
something tells me that it's a bank account NUMBER... not balance. In which case I have to question why it's being treated as a number... at worst, it's a string. at best, two numbers... the routing or ATA number and the actual account number, which should be MUCH shorter than 31 digits... I can see it being close to 31 digits with the ATA number... but most account numbers are 10-12 digits long depending on the numbering schema of the bank. Ultra worst case, you break it up into pieces and pack each piece into an array.
guys, this long number is an account number (IBAN) decomposed and i need to check if it is correct. For that, the book says that it must be divided with 97. If i use currency it gives me as a result something like: 1,0101013162E28+29. I don't know how to interpret this. Sorry for my english !!! i'm from romania
Condensing down that truly awful code offered by the Central Bank of Malta...
... there isn't much to it.
No long numbers at all, you just have to look up the algorithm and go, or as in this case find some working but nasty code and clean it up.
Code:
Function Validate_IBAN(ByVal Account As String) As Boolean
Dim intChar As Integer
Dim strChar As String
Account = UCase$(Account)
If Len(Account) > 4 Then Account = Mid$(Account, 5) & Left$(Account, 4)
intChar = Len(Account)
Do While intChar > 0
strChar = Mid$(Account, intChar, 1)
If strChar Like "[A-Z]" Then
'55 = Asc("A") - 10
Account = Left$(Account, intChar - 1) _
& CStr(Asc(strChar) - 55) _
& Mid$(Account, intChar + 1)
End If
intChar = intChar - 1
Loop
Do While Len(Account) > 5
Account = CStr(CLng(Left$(Account, 5)) Mod 97) & Mid$(Account, 6)
Loop
Validate_IBAN = (CLng(Account) Mod 97) = 1
End Function
Seems to work against the handful of examples I found (included in the program in a dropdown ComboBox).
For that, the book says that it must be divided with 97.
The IBAN (converted to an integer) needs to be checked to be equal to 1 mod 97, not 0. Using regular integer division wouldn't have worked anyway. What you wanted was the remainder when divided by 97, which is what dilettante's code finds. [It can be proven correct with a little basic modular arithmetic.] To be honest, with the incredibly low quality of the Malta code, I'm surprised it's correct, but it seems to be.
The time you enjoy wasting is not wasted time. Bertrand Russell
Jemidiah said, "... To be honest, with the incredibly low quality of the Malta code, I'm surprised it's correct, but it seems to be."
----------------
I hate to sound philosophical, but if code works that nobody else can improve upon, then it seems to me that such code cannot be of low quality.
I've written code that outruns API equivalents, but everybody said it was out of date and low quality because I should have used the API instead in order to be "up to date".
In some cases I'd agree. In this case dilettante compressed over two and a half pages of code that barely worked into a ~20 line routine with way better style. For instance, the original author used the "Str" function instead of CStr and seems to have tried random things including applying the Format function to get rid of the extra space. They didn't give their variables types, "tempinteger" is actually a string variant, they used a huge select case block when a small amount of character code logic sufficed, their variable names are awful, etc. The code works, but it can be vastly improved.
The time you enjoy wasting is not wasted time. Bertrand Russell
In some cases I'd agree. In this case dilettante compressed over two and a half pages of code that barely worked into a ~20 line routine with way better style. For instance, the original author used the "Str" function instead of CStr and seems to have tried random things including applying the Format function to get rid of the extra space. They didn't give their variables types, "tempinteger" is actually a string variant, they used a huge select case block when a small amount of character code logic sufficed, their variable names are awful, etc. The code works, but it can be vastly improved.
+1. Thanks for the clarification.
I had a high school algebra instructor who always said, "Simplify, simplify, simplify." He knew what he was talking about.
Condensing down that truly awful code offered by the Central Bank of Malta...
... there isn't much to it.
No long numbers at all, you just have to look up the algorithm and go, or as in this case find some working but nasty code and clean it up.
Code:
Function Validate_IBAN(ByVal Account As String) As Boolean
Dim intChar As Integer
Dim strChar As String
Account = UCase$(Account)
If Len(Account) > 4 Then Account = Mid$(Account, 5) & Left$(Account, 4)
intChar = Len(Account)
Do While intChar > 0
strChar = Mid$(Account, intChar, 1)
If strChar Like "[A-Z]" Then
'55 = Asc("A") - 10
Account = Left$(Account, intChar - 1) _
& CStr(Asc(strChar) - 55) _
& Mid$(Account, intChar + 1)
End If
intChar = intChar - 1
Loop
Do While Len(Account) > 5
Account = CStr(CLng(Left$(Account, 5)) Mod 97) & Mid$(Account, 6)
Loop
Validate_IBAN = (CLng(Account) Mod 97) = 1
End Function
Seems to work against the handful of examples I found (included in the program in a dropdown ComboBox).
== see: http://en.wikipedia.org/wiki/Interna...Account_Number
-- Rule process of IBAN validation is:
-- 1. Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid.
-- 2. Move the four initial characters to the end of the string.
-- 3. Replace each letter in the string with two digits, thereby expanding the string,
-- where A=10, B=11, ..., Z=35.
-- 4. Interpret the string as a decimal integer and compute the remainder of that number on division by 97.
-- If the remainder is 1, the checks digits test is passed and the IBAN may be valid.
Code:
Function Validate_IBAN(ByVal IBAN As String) As Boolean
Dim i As Long
Dim n As Long
IBAN = Replace(IBAN, " ", "") '-- space separator accepted, remove it before processsing
If IBAN Like "*[!0-9A-Z]*" Then Exit Function '-- contains invalid character
'-- step 1. (simplified)
If Len(IBAN) < 5 Or Len(IBAN) > 31 Then Exit Function
'-- step 2.
IBAN = Mid$(IBAN, 5) & Left$(IBAN, 4)
'-- step 3.
For i = 65 To 90
If InStr(IBAN, Chr$(i)) Then IBAN = Replace(IBAN, Chr$(i), CStr(i - 55))
Next
'-- step 4.
n = CLng(Left$(IBAN, 9)) Mod 97
For i = 10 To Len(IBAN)
n = (n * 10 + CLng(Mid$(IBAN, i, 1))) Mod 97
Next
'-- n can be calculated by using function BigMod: n = BigMod(IBAN, 97)
Validate_IBAN = (n = 1)
End Function
Code:
Sub TryIt()
Dim i As Long
Dim IBAN(4) As String
IBAN(0) = "GR16 0110 1250 0000 0001 2300 695" '-- Greece
IBAN(1) = "GB29 NWBK 6016 1331 9268 19" '-- Great Britain
IBAN(2) = "SA03 8000 0000 6080 1016 7519" '-- Saudi Arabia
IBAN(3) = "CH93 0076 2011 6238 5295 7" '-- Switzerland
IBAN(4) = "IL62 0108 0000 0009 9999 999" '-- Israel
For i = 0 To 4
Debug.Print i; Validate_IBAN(IBAN(i))
Next
Debug.Print
End Sub
Code:
Function BigMod(BigInt As String, k As Long) As Long
'-- pre: BigInt contains only digits, k > 0
Dim i As Long
BigMod = CLng(Left$(BigInt, 9)) Mod k
For i = 10 To Len(BigInt)
BigMod = (BigMod * 10 + CLng(Mid$(BigInt, i, 1))) Mod k
Next
End Function
Don't forget to use [CODE]your code here[/CODE] when posting code
If your question was answered please use Thread Tools to mark your thread [RESOLVED]