Results 1 to 23 of 23

Thread: generating 14 digits based on the following

  1. #1

    Thread Starter
    New Member
    Join Date
    Sep 2015
    Posts
    4

    generating 14 digits based on the following

    I am developing a database application. The user will enter his/her particulars in a form. Once they click on the register button, those data fields will be stored in a database.

    What i want to do is, once clicked on the register button, a 14 digits is generated an recorded in the database as the unique identifier key. Those digits are based on the last 2 digit of the current registration year, his/her birth date which is 8 digits, a serial number start at 1 (leaded by two zeros eg 001, 001)which increment by one every time the register button is clicked, and lastly a check digit.

    eg 15071990110014


    This is my code, the id does not increment every time this function is called.

    Code:
    Private id As Integer
    
    Public Function generateUniqueNumber() As Long
        id += 1
        Dim curDate As Date = DateTime.Today
        Dim regYear As Integer = curDate.Year.ToString.Substring(2)
    
        Dim dob As Integer = CInt(BirthDate)
        Dim vID As String = id.ToString("D3")
        Dim uniqueID As String = regYear & dob & vID
    
    
        Dim r, sum As Integer
        While uniqueID <> 0
            r = uniqueID Mod 10
            sum += r
            uniqueID \= 10
        End While
    
    
        Dim checkDigit As Decimal = 0
        Dim reminder As Decimal = 0
    
        reminder = sum Mod 10
        If reminder = 0 Then
            checkDigit = 0
        Else
            checkDigit = 10 - reminder
        End If
    
        Dim uid As Long = regYear & "" & dob & "" & vID & "" & checkDigit
    
    
        Return uid
    End Function

  2. #2
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,755

    Re: generating 14 digits based on the following

    I don't see why your id does not increment, because you're explicitly calling id += 1. What you should do is setup a breakpoint on your line that increments id and where you declare and use vID and watch those variables.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  3. #3

    Thread Starter
    New Member
    Join Date
    Sep 2015
    Posts
    4

    Re: generating 14 digits based on the following

    Quote Originally Posted by dday9 View Post
    I don't see why your id does not increment, because you're explicitly calling id += 1. What you should do is setup a breakpoint on your line that increments id and where you declare and use vID and watch those variables.
    Hey dday, thanks for your quick reply. I did what you said, and the 'id' does increment.. I don't know, the function returns the same number every time is called.

  4. #4
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,755

    Re: generating 14 digits based on the following

    Wait, I think I know what is happening. Do not declare uid as a long, declare it as a String and setup a breakpoint on that line.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,041

    Re: generating 14 digits based on the following

    Well, it may have something to do with the fact that you are creating a large string and assigning it to a Long datatype using an implicit conversion (and why are you concatenating in empty strings periodically?). I don't see why that wouldn't work, but it isn't a good idea, and it may well be the problem.

    What I would do first would be to put a breakpoint on the return line. When execution stops on that line, highlight ALL of this:

    regYear & "" & dob & "" & vID & "" & checkDigit

    and press Shift+F9 to see what you get. If it looks right, then the next thing to do would be to make that into an explicit conversion like so:

    Return CLong(regYear & "" & dob & "" & vID & "" & checkDigit)

    (you can get rid of the uid variable, since it isn't really necessary).

    If that solves the problem....well, that would be interesting. If it does NOT solve the problem then I would say that the problem is not in the code you have shown.
    My usual boring signature: Nothing

  6. #6
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: generating 14 digits based on the following

    If the code that creates this is in a class, then id will be 0 each time it's initialized. If that class is being instantiated each time, well, you'll get 001 every time for the sequential ID. Or each time the application starts. The only "safe" way to have an incrementing check like this is to persist it somewhere and load it each time, but then if multiple applications are accessing the database you also need some form of guarantee that two can't get the same value back at the same time. It's much, much easier to just use GUIDs if you need a globally unique identifier. They were designed by very smart people and collisions tend to be human error.

    I'm surprised it works at all, though. & is for string concatenation, and we're attempting to build a Long... that should be a compile error.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  7. #7
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,041

    Re: generating 14 digits based on the following

    No, it won't be a compile error with Option Strict OFF, because you end up with a string that is implicitly converted to a Long. It would be inefficient, but not an error.

    I agree, though, that the problem is quite possibly not in the code shown.
    My usual boring signature: Nothing

  8. #8

    Thread Starter
    New Member
    Join Date
    Sep 2015
    Posts
    4

    Re: generating 14 digits based on the following

    Thanks everybody, but none of the above worked for me. @Sitten Spynne, yes the code is in a class...

    I would be very thankful if any of you could provide me with a working code that solves this problem.

  9. #9
    PowerPoster kaliman79912's Avatar
    Join Date
    Jan 2009
    Location
    Ciudad Juarez, Chihuahua. Mexico
    Posts
    2,593

    Re: generating 14 digits based on the following

    Consider that even if it works it will only be effective for the current run. If you exit your application, or even close the form (or class) id will start again thus not giving you the desired effect. If you are storing this in a database file why not use an identity column (autonumber in access) and use that value to fill your uid?
    More important than the will to succeed, is the will to prepare for success.

    Please rate the posts, your comments are the fuel to keep helping people

  10. #10
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,755

    Re: generating 14 digits based on the following

    Try using this code:
    Code:
    Public Class User
    
    	Private _id As Integer
    	Public ReadOnly Property ID As Integer
    		Get
    			Return _id
    		End Get
    	End Property
    
    	Private _dob As DateTime
    	Public Property DateOfBirth As DateTime
    		Get
    			Return _dob
    		End Get
    		Set(ByVal value As DateTime)
    			_dob = value
    		End Set
    	End Property
    
    	Public Function generateUniqueNumber() As String
    		'Increment the ID
    		_id += 1
    
    		Dim uniqueID As Long = CLng(DateTime.Now.ToString("yy") & _dob.ToString("mmddyyyy") & _id.ToString("D3"))
    		Dim r, sum As Integer
    		While uniqueID <> 0
    			r = uniqueID Mod 10
    			sum += r
    			uniqueID \= 10
    		End While
    
    
    		Dim checkDigit As Decimal = 0
    		Dim reminder As Decimal = 0
    
    		reminder = sum Mod 10
    		If reminder = 0 Then
    			checkDigit = 0
    		Else
    			checkDigit = 10 - reminder
    		End If
    		
    		'Return: <last two digits of current year> & <date of birth> & <ID> & <checkDigit>
    		Return DateTime.Now.ToString("yy") & _dob.ToString("mmddyyyy") & _id.ToString("D3") & checkDigit
    	End Property
    
    End Class
    I tested it with this module and it works as expected:
    Code:
    Imports System
    
    Public Module Module1
    
        Public Sub Main()
            Dim foo As User = New User() With {.DateOfBirth = New DateTime(1991, 8, 12)}
            Console.WriteLine(foo.generateUniqueNumber())
            Console.WriteLine(foo.generateUniqueNumber())
            Console.WriteLine(foo.generateUniqueNumber())
        End Sub
    End Module
    
    Public Class User
    
        Private _id As Integer
        Public ReadOnly Property ID As Integer
            Get
                Return _id
            End Get
        End Property
    
        Private _dob As DateTime
        Public Property DateOfBirth As DateTime
            Get
                Return _dob
            End Get
            Set(ByVal value As DateTime)
                _dob = value
            End Set
        End Property
    
        Public Function generateUniqueNumber() As String
            _id += 1
            Dim uniqueID As Long = CLng(DateTime.Now.ToString("yy") & _dob.ToString("mmddyyyy") & _id.ToString("D3"))
            Dim r, sum As Integer
            While uniqueID <> 0
                r = uniqueID Mod 10
                sum += r
                uniqueID \= 10
            End While
    
            Dim checkDigit As Decimal = 0
            Dim reminder As Decimal = 0
            reminder = sum Mod 10
            If reminder = 0 Then
                checkDigit = 0
            Else
                checkDigit = 10 - reminder
            End If
    
            'Return: <last two digits of current year> & <date of birth> & <ID> & <checkDigit>
            Return DateTime.Now.ToString("yy") & _dob.ToString("mmddyyyy") & _id.ToString("D3") & checkDigit
        End Function
    End Class
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  11. #11
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,041

    Re: generating 14 digits based on the following

    If it didn't work, then the problem is not in the code you posted, so we have no way to suggest anything because we don't know the rest of the code. However, just telling us "it doesn't work" doesn't help all that much. I suggested a breakpoint and looking at something specific. If the value at that point looked right, then you could also look at the CLong conversion (which is better than the implicit conversion you were using, regardless of whether or not it fixed anything) and see if the result is right or wrong. You could tell us about the results of those two checks, but if the number is right after the CLong conversion, as it should be, then the problem is certainly not in that code.
    My usual boring signature: Nothing

  12. #12
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: generating 14 digits based on the following

    I still don't really understand why we're trying to improve on GUID, which is already guaranteed to be unique and doesn't require a lot of extra work. :/
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  13. #13
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,537

    Re: generating 14 digits based on the following

    If it's strictly for the database, I agree... if it's for user consumption... I still agree... with a caveat. we use GUIDs for our PKeys in our tables. For tables where we also need a user-friendly Identifier, we use a Sequence field and a computed field. The Sequence field is essentially like an Identity field... the computed field then takes that value pads it with 0's and then prepends the value with the prefix. The prefix helps define what it is. Invoices use "Inv" events use "Evt" .... so it looks like this "Inv-0000001"

    So I'd still use the GUID for the table pkey, but maybe a computed col for putting together a user-friendly ID.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  14. #14
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: generating 14 digits based on the following

    Quote Originally Posted by Sitten Spynne View Post
    I still don't really understand why we're trying to improve on GUID, which is already guaranteed to be unique and doesn't require a lot of extra work. :/
    Guaranteed unique? Not really.

    I wouldn't say it's a lot of extra work to generate an application specific unique ID number; it just seems that way, here, because there's also a learning process going on.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  15. #15
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: generating 14 digits based on the following

    You'll have to qualify that. The probabilities do vary wildly by implementation but even the ones that use an RNG have 2^122 possibilities. That's a pretty large number space. The Wikipedia quote is that for a 50% probability of collision the 2014 world population would have to own 600 million GUIDs per person. I bet this database app doesn't reach 600m records, let alone 600m * a world population.

    So you're comparing an algorithm with a strongly random distribution across a 2^122 number space when implemented poorly to one that only uses 25 of available 64 bits; the rest of them are either fixed or weakly random. It'll probably work out fine, but we're so many orders of magnitude apart it makes no sense if uniqueness is the only requirement.

    Techgnome's situation makes some sense, because in that case the number's uniqueness isn't the most desirable quality and there's other constraints that ensure a smaller space will be unique. But if you routinely dismiss GUID because it isn't guaranteed enough for you I can't fathom what would satisfy you.

    This is a problem completely solved by one line, unless there's some reason why this 14-digit identifier is required, like "must be printed on a barcode and the format is 14 digits". It's like you were asked if a shoe or a wine bottle did a better job driving nails, and happily demonstrated a shoe technique. It makes me frown to teach people to distrust proven algorithms. Those kinds of bad habits are very hard to break.
    Last edited by Sitten Spynne; Sep 9th, 2015 at 06:53 PM.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  16. #16
    PowerPoster kaliman79912's Avatar
    Join Date
    Jan 2009
    Location
    Ciudad Juarez, Chihuahua. Mexico
    Posts
    2,593

    Re: generating 14 digits based on the following

    VB Coder's is asking us to help him generate his personal and very specific 14 character ID, that we do not need to question. He is not asking for a different solution so I think regardless of the collision probability, GUID is not appropriate here.
    More important than the will to succeed, is the will to prepare for success.

    Please rate the posts, your comments are the fuel to keep helping people

  17. #17
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: generating 14 digits based on the following

    We should always question, sometimes we choose the wrong solution for a problem.

    It's not stupid to want some kind of customized 14-digit ID. But so far the only requirement is "I need a unique identifier". No one's done anything but speculate as to why that specific algorithm is needed. But only VB Coder can tell us if there is, indeed, some reason. The best solution, given no other context, is a GUID.

    It's as if a friend calls you and asks for the best way to use a chainsaw to slice pizza. It'd be very strange indeed to respond with anything but, "Uh, why aren't you using a knife or a pizza cutter?" More often than not, I find the response to that request is "Oh, right, I had a chainsaw in my hand and it seemed convenient, I'll get a knife." SOMETIMES the answer is something like, "I'm on a game show and I have to use a chainsaw." In that case, a chainsaw becomes the best tool because now we have some constraints that require it.

    I find the same thing on programming forums. Often, people find a problem and try to solve it, then come here asking for the best way to make their solution work. Sometimes they've chosen the wrong solution, so while it's fun to make that solution work it's the chainsaw/pizza scenario, and people waste lots of time and energy describing how to perform a task that's best accomplished another way.

    This is "results-oriented" thinking, the idea that nothing matters if the program works in the end. That is folly, for every problem there are hundreds of solutions ranging from "provably correct and maintainable" to "only works for specific inputs and obfuscated beyond reason". I don't think I'm here to provide the shortest or fastest answer. I'm here to provide the answer most like the code I'd like to find in my own codebase, and explain why I believe my methods have more merit than other approaches.

    So, if your name isn't 'VB Coder', I'm not accepting reasons why the 14-digit semi-random number is superior to a GUID. Given no other context, a GUID is the shortest path to success. Until that context is provided, everything else is wasted effort.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  18. #18
    PowerPoster kaliman79912's Avatar
    Join Date
    Jan 2009
    Location
    Ciudad Juarez, Chihuahua. Mexico
    Posts
    2,593

    Re: generating 14 digits based on the following

    I appologize in advance if this sounds harsh... Wasted effort? that's what i call a 400 word paragraph explaining something that was not asked for, but not just to be a pain, if we are suggesting solutions, GUID is overkill, just use an identity column, really the shortest path.
    More important than the will to succeed, is the will to prepare for success.

    Please rate the posts, your comments are the fuel to keep helping people

  19. #19
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,755

    Re: generating 14 digits based on the following

    Let's simmer down y'all. I think the consensus is, is that there are multiple ways to skin a cat. As of right now the only information we know is what the OP has provided us with. Until then take a step back and allow the OP to proceed.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  20. #20
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: generating 14 digits based on the following

    I looked at/tested DDay's solution and it seemed to do what's required, with a couple of minor changes (Long instead of integer, and MM instead of mm in the date format), but nothing that basic debugging won't sort out.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  21. #21
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,041

    Re: generating 14 digits based on the following

    One thing about the initial post was that the ID number certainly is not random. In fact, it is just an encoding of several pieces of data. There may well be a reason for that encoding that specifically precludes randomness in the number (which isn't currently there). I've seen plenty of such systems. After all, the ID asked for can be sorted in several interesting ways because of the information contained in the sequence of digits.
    My usual boring signature: Nothing

  22. #22

    Thread Starter
    New Member
    Join Date
    Sep 2015
    Posts
    4

    Re: generating 14 digits based on the following

    Thanks everyone who took part of this discussion. This was the requirement for an assignment project. This 14 digits are actually unique until the number 999 because the serial number are incremented. I just had to submit but I will still be interesting in implementing it in this way.

    @dday9 your code work fines, but does not increment when I embed into my source code. I'll try to figure it!

  23. #23
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,764

    Re: generating 14 digits based on the following

    My $.02

    Code:
        Private Function generateUniqueNumber(birthday As Date) As String
            Dim serno As Integer = GetSerno(birthday)
            Dim twoDigitYr As Long = Date.Now.Year Mod 100
            Dim uniq As Long
            uniq = serno
            uniq = uniq Or birthday.Day << 10 ' serno 10 bits
            uniq = uniq Or birthday.Month << 15 ' day 5 bits
            uniq = uniq Or CLng(birthday.Year) << 19 ' month 4 bits
            uniq = uniq Or twoDigitYr << 33 'year 14 bits
            'calc check
            Dim temp As Long = uniq
            Dim chk As Long
            Do While temp > 0L
                chk += temp And &HFL
                temp = temp >> 4
            Loop
            chk = chk Mod 10
            ' check takes 4 bits
            uniq = uniq << 4 Or chk
            Return uniq.ToString.PadLeft(14, "0"c)
        End Function
    
        Private Function GetSerno(birthday As Date) As Integer
            Static bds As New Dictionary(Of Date, Integer)
            Dim tempBD As New Date(DateTime.Now.Year, birthday.Month, birthday.Day)
            If Not bds.ContainsKey(tempBD) Then
                bds.Add(tempBD, 0)
            End If
            bds(tempBD) += 1
            If bds(tempBD) > 999 Then
                Throw New ArgumentOutOfRangeException("exceed serno for bd")
            End If
            Return bds(tempBD)
        End Function
    This allows 999 people with the same birthday to register in the same year so long as you saved / loaded the dictionary between runs of the program.

    If this was real world the other discussions should be considered.
    Last edited by dbasnett; Sep 11th, 2015 at 06:36 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

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