Random() generating repeated numbers

Asked

Viewed 2,080 times

8

I am developing a small application to perform XML import, which searches the items present in the note and performs the search for them in DB company. When the item is not found, the link is done manually and this information is saved in a table ItemFornecXItemEmpresa and, next time, the program will find the item.

My problem is in the generation of ObjID, which is generated based on the day and time of insertion and plus 5 random numbers:

for (int i = 0; i < itens.Count; i++)
{
    if (itens[i].Novo == true)
    {
        Random rand = new Random();
        string ano = String.Format("{0:yy}", DateTime.Now);
        string mes = String.Format("{0:MM}", DateTime.Now);
        string dia = String.Format("{0:dd}", DateTime.Now);
        string hora = String.Format("{0:hh}", DateTime.Now);
        string mili = String.Format("{0:ff}", DateTime.Now);
        string random = rand.Next(10000,99999).ToString();

    string id = ano + mes + dia + hora + mili + random;
    [...]
    }
}

And every insertion I make I have that kind of ID generated:

150325094512431
1503250946*44723*
1503250947*44723*
150325094929997
150325095062289
1503250951*94581*
1503250952*94581*
201513031638315
201516031131187
201516031136284
201516031137201

I observe several IDs repeated. There is some logic to this?

  • 1

    I think it would be better to use an Identity column in the database (assuming SQL Server), or UUID, and save the date in a separate location. The identifier is not a good place to store record creation date and time.

  • The idea is to generate unrepeated numbers using the date as the basis for @bfavaretto actually, and not to store the date properly. Anyway, it won’t be an app for distribution, just for testing.

  • 1

    I get it. With the solution of the bigown, I understand that the numbers will no longer repeat themselves inside the loop, but nothing prevents them from repeating themselves between several executions of this block of code that you posted (which I assume is in a function). Even if you created a guard for this, sooner or later they would repeat themselves, since there are a not so large amount of numbers in the range that you have determined.

  • 1

    The random number will repeat itself sooner or later, no doubt, that’s where the date and time comes in, because when the string Random repeat, it will be another day (or year). If it is the same day, it will be another time. I think I’ll have no problem with it the way it is (for my application size, of course). But thanks for the remark.

  • 1

    In this case would not it be much better to use sequential instead of Random? It’s increasing one by one, which by about 100,000 increments probably the minute has already changed.

1 answer

10


Yes, there is. Your code is initiating the random seed every time inside the loop. So it will repeat itself. If you want different values you should start the seed only once, that is, you should remove the initialization of the loop variable. So (I took the opportunity to simplify):

var rand = new Random();
for (int i = 0; i < itens.Count; i++) {
    if (itens[i].Novo) 
        var id = $"{DateTime.Now:yy}{DateTime.Now:MM}{DateTime.Now:dd}{DateTime.Now:hh}{DateTime.Now:ff}{rand.Next(10000, 99999)}";
        [...]
    }
}

I put in the Github for future reference.

There’s an important detail, I think I’d better keep the DateTime.Now in a variable and use it. It may be rare to happen but there will be some case that the mount will be inconsistent. In an extreme case it can give a difference of one year. If the operation starts in the last second of the year, almost to turn, then you can take the current year in the first printing, when it will take the month already turned, then it considers January because the year is already another, only it was printed the year before, look at the shit nonsense that gives. It could happen with month, day, hour, minute or even the error of 1 second. And the fact of using a random makes it highly unlikely, but possible to give a conflict, so every concept seems wrong.

If you want it to be unique and chronological maybe you should use a more precise time going beyond the second, or do sequence taking care to have some form of exclusivity in obtaining the sequential number. If you only want a random name and no matter the chronology then you should use the OS API or a standard library that provides a guaranteed unique name.

To better understand and see examples of use read carefully all documentation from Random().

See an example demonstrating the problem:

using System;
using static System.Console;
                    
public class Program {
    public static void Main() {
        var rand = new Random();
        for (int i = 0; i < 10; i++) {
            WriteLine(rand.Next(10000,99999));
        }
        WriteLine();
        for (int i = 0; i < 10; i++) {
            rand = new Random();
            WriteLine(rand.Next(10000,99999));
        }
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

  • Wow, awesome for me. Is there a reason for this repetition? I mean, start a new instance of Random() each loop may not be correct, but it should generate different numbers, no?

  • @Cassiomilanelo depends on. Random() uses a temporal seed Environment.TickCount. If several instances are created in rapid succession, the seed ends up being the same (due to the precision of the TickCount).

  • No. That’s the thing about it, the computer can’t generate random fact numbers. There are ways to help with that. You could keep your logic and get different numbers but the most correct one in logic is this. This function should generate sequences of numbers that can be reproduced. To understand more about this: http://answall.com/q/9026/101

Browser other questions tagged

You are not signed in. Login or sign up in order to post.