C# generate bit string randomly "0001", "1010", etc - c#

I need to generate a 4 bit string randomly and set to a property via Linq.
Right now is hardcoded:
// TODO: hardcode bit string
employees = employees.Select(x => { x.Options = "0101"; return x; }).ToList();
I need Options to be random so I can get all 4 bit possible values: "0001","0010", "0011" and so on.
I was thinking on having a Random 0 to 1 variable and generate the value 4 times and concatenate the string.
Any clue on how to implement this?

If speed is critical, such as this operating being called in a loop, it would be more efficient to use a 16 element string array of all possible values and select the element randomly.

var rand = new Random();
Convert.ToString(rand.Next(16), 2).PadLeft(4, '0')
Explanation:
The first line creates a random object, nothing too hard to understand here... The second line first generates a random number between 0 - 15 (rand.Next(16)). Then it puts the random number into Convert.ToString. The method converts to number to base 2 (because the second parameter is 2). However, this still is not enough because if the random number can be represented by 3 bits or fewer, the returned string will not have the leading 0s. That's why I used PadLeft to add them in.

You can use this
Convert.ToString(int, 2);
This will convert the int to base 2 string.
Where int is a random number up to 16 not included.

Related

Is Guid.NewGuid().ToByteArray() to a string (number) line still unique

I need to generate a unique id which consists of numbers.
Is the following result string uniqueId as unique as the result of guid.ToString()?
Guid guid = Guid.NewGuid();
byte[] guidBytes = guid.ToByteArray();
// Is the result (uniqueId) as unique as guid.ToString()?
string uniqueId = string.Join(string.Empty, guidBytes);
You need seperator between byte values or fill with zero. Otherwise there is intersection.
Example: 3,5,6,7,123 => 003005006007123
Yes, there is a 1:1 mapping of byte arrays to Guids. No information is lost during the transformation so you still retain the same uniqueness as using the normal string representation of a Guid.
A Guid really is just a 16 byte number, it does not matter if you show it as {3F2504E0-4F89-41D3-9A0C-0305E82C3301}, 4AQlP4lP00GaDAMF6CwzAQ== or as 224004037063137079211065154012003005232044051001, it all still represents the same number.
EDIT: Oops, as mkysoft ponted out, you do have to deal with leading zeros. Padding the numbers to 3 digits solves the issue
var guid = new Guid("{3F2504E0-4F89-41D3-9A0C-0305E82C3301}");
Console.WriteLine(string.Join(string.Empty, guid.ToByteArray().Select(x=>x.ToString("000"))));
UPDATE: Actually I just thought of a better solution, a Guid is a 128-bit number, by using 2 64-bit numbers and padding the number's 0's out on the 2nd half you will get a shorter, but still unique number.
var guid = new Guid("{3F2504E0-4F89-41D3-9A0C-0305E82C3301}");
var guidBytes = guid.ToByteArray();
Console.WriteLine("{0}{1}", BitConverter.ToUInt64(guidBytes, 0), BitConverter.ToUInt64(guidBytes,8).ToString().PadLeft(20, '0'));
This will output a unique integer number that is between 21 and 40 digits long, {3F2504E0-4F89-41D3-9A0C-0305E82C3301} becomes 474322228343976880000086462192878292122,
Or you could use BigInteger.ToString() to handle making big numbers into strings (since it's really good at that)
var p = Guid.NewGuid().ToByteArray();
Array.Resize(ref p, p.Length + 1);
Console.WriteLine(new BigInteger(p));
The resize is only if you require positive numbers (otherwise there is a 50% chance you get a negative number). You could also use System.Security.Cryptography.RandomNumberGenerator.GetBytes to have a larger or smaller set of values (depending on how big you want your identifiers to be)

Find the minimum of a number sequence with negative numbers with Linq

The following code doesn't give the expected minimum -1. Instead I get 0.
Do you know why?
class MainClass
{
public static void Main (string[] args)
{
string numbers = "-1 0 1 2 3 4 5";
Console.WriteLine (numbers.Split (' ')[0]); // output: -1
string max = numbers.Split(' ').Max();
string min = numbers.Split(' ').Min();
Console.WriteLine("{0} {1}", max, min); // output: "5 0"
}
}
I've not fully defined an answer yet but it appears to be because the - isn't accounted for.. you can confirm this with CompareOrdinal
Console.WriteLine(String.CompareOrdinal("-1", "0")); // -3 meaning -1 min
Console.WriteLine(String.Compare("-1", "0")); // 1 meaning 0 min
Either way, you are trying to compare numbers so you should treat them as numbers so similar subtleties dont appear.
Attempted explanation...
String implements IComparable<string> so String.Min uses that implementation (see remarks). Which in turn uses CompareTo,
Now in the notes for this method
Character sets include ignorable characters. The CompareTo(String) method does not consider such characters when it performs a culture-sensitive comparison. For example, if the following code is run on the .NET Framework 4 or later, a comparison of "animal" with "ani-mal" (using a soft hyphen, or U+00AD) indicates that the two strings are equivalent.
(Emphasis mine)
As you see. the - is ignored hence 0 which has a smaller value in an ascii table is used for the comparison
It's a string so Getting max from string is totally different than getting max from a number. For instance if You would have an array like below
char[] someCharArray = new char[] { '1', '12', '2' }
calling Max() on this array would result with 2 as 2 is "higher" in string order than 12.
Thinking about Max/Min value from string/char You need to think about alphabetical order. If You have a colection of letters A-Z, calling Min() will return A, calling Max() will return Z.
To get Max/Min in numerical order You need to cast to some Number type like int.
See below:
string numbers = "-1 0 1 2 3 4 5";
int min = numbers.Split(' ').Select(x => int.Parse(x)).Min();
Console.WriteLine(min); // gives You -1
There are two reasons for this behaviour:
You are sorting strings instead of numbers. This means that behind the scenes, Linq is using String.CompareTo() to compare the strings.
String.CompareTo() has special behaviour for -, which it treats as a HYPHEN and not a MINUS. (Note: This hyphen should not be confused with a soft hyphen which has the character code U00AD.)
Consider this code:
Console.WriteLine("-1".CompareTo("0")); // 1
Console.WriteLine("-1".CompareTo("1")); // 1
Console.WriteLine("-1".CompareTo("2")); // -1
Notice how, counter-intuitively, the "-1" is AFTER "0" and "1" but BEFORE "2".
This explains why when ordering the strings, the "-1" is neither the max nor the min.
Also see the answer to this question for more details.

Generate a Random Int32 for the full range of possible numbers

If I wanted to generate a random number for all possible numbers an Int32 could contain would the following code be a reasonable way of doing so? Is there any reason why it may not be a good idea? (ie. a uniform distribution at least as good as Random.Next() itself anyway)
public static int NextInt(Random Rnd) //-2,147,483,648 to 2,147,483,647
{
int AnInt;
AnInt = Rnd.Next(System.Int32.MinValue, System.Int32.MaxValue);
AnInt += Rnd.Next(2);
return AnInt;
}
You could use Random.NextBytes to obtain 4 bytes, then use BitConverter.ToInt32 to convert those to an int.
Something like:
byte[] buf = new byte[4];
Rnd.NextBytes(buf);
int i = BitConverter.ToInt32(buf,0);
Your proposed solution will slightly skew the distribution. The minValue and maxValue will occur less frequently than the interior values. As an example, assume that int has a MinValue of -2 and a MaxValue of 1. Here are the possible initial values, with each followed by the resulting values after the Random(2):
-2: -2 -1
-1: -1 0
0: 0 1
half of the negative -2 values will get modified up to -1, and only half of 0 will get modified up to 1. So the values -2 and 1 will occur less frequently than -1 and 0.
Damien's solution is good. Another choice would be:
if (Random(2) == 0) {
return Random(int.MinValue, 0);
} else {
return 1 + Random(-1, int.MaxValue);
}
another solution, similar to Damiens approach, and faster than the previous one would be
int i = r.Next(ushort.MinValue, ushort.MaxValue + 1) << 16;
i |= r.Next(ushort.MinValue, ushort.MaxValue + 1);
A uniform distribution does not mean you get each number exactly once. For that you need a permutation
Now, if you need a random permutation of all 4-billion numbers you're a bit stuck. .NET does not allow objects to be larger than 2GBs. You can work around that, but I assume that's not really what you need.
If you less numbers (say, 100, or 5 million, less than a few billions) without repetitions, you should do this:
Maintain a set of integers, starting empty. Choose a random number. If it's already in the set, choose another random number. If it's not in the set, add it and return it.
That way you guarantee each number will be returned only once.
I have a class where I get random bytes into a 8KB buffer and distribute numbers from by converting them from the random bytes. This gives you the full int distribution. The 8KB buffer is used to you do not need to call NextBytes for every new random byte[].
// Get 4 bytes from the random buffer and cast to int (all numbers equally this way
public int GetRandomInt()
{
CheckBuf(sizeof(int));
return BitConverter.ToInt32(_buf, _idx);
}
// Get bytes for your buffer. Both random class and cryptoAPI support this
protected override void GetNewBuf(byte[] buf)
{
_rnd.NextBytes(buf);
}
// cyrptoAPI does better random numbers but is slower
public StrongRandomNumberGenerator()
{
_rnd = new RNGCryptoServiceProvider();
}

Random.Next returns always the same values [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
I use the method to generate unique number but I always get the same number -2147483648. Even if I stop the program, recompile it and run again I still see the same number.
public static int GetRandomInt(int length)
{
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
var random = new Random();
return random.Next((int)min, (int)max);
}
Try externalizing the random instance:
private readonly Random _random = new Random();
public static int GetRandomInt(int length)
{
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
return _random.Next((int)min, (int)max);
}
This is not an issue of not reusing Random instance, the results he gets should be random on multiple starts, not always being -(2^32)
This is the issue with length being too big, and casting powers of length to int. If you break the code into following lines:
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
var random = new Random();
var a = (int)min;
var b = (int)max;
return random.Next(a, b);
You'll see that a and b are -2147483648, making that the only possible result of Next(min, max) (the doc specifies if min==max, return min).
The largest length you can safely use with this method is 9. For a length of 10 you'll get System.ArgumentOutOfRangeException, for length > 10 you'll get the -2147483648 result.
You have three problems with your code.
You should externalize your random variable.
You have a problem with truncation error.
The range between min and max is way to large.
The first problem is because you may not have enough time to advance the seed when reinitializing your random variable. The second error comes from truncating your (what would b very large) numbers down to ints. Finally, your biggest problem is your range between your min and your max. Consider finding the range between min and max (as defined in your code) with inputs 1->20:
length max-min
1 8
2 89
3 899
4 8999
5 89999
6 899999
7 8999999
8 89999999
9 899999999
10 8,999,999,999
11 89999999999
12 899999999999
13 8999999999999
14 89999999999999
15 899999999999999
16 9E+15
17 9E+16
18 9E+17
19 9E+18
And keep in mind that the maximum integer is 2,147,483,647, which is passed on any number greater than 9.
You should keep an instance of Random and not new() it up all the time, that should give you better results.
Also check for what length actually is. It may be giving you funny results as to the limits.
I think the problem is the calculation of min and max. They will be greater than Int32.MaxValue pretty fast...
In your class, have one instance of Random, e.g.:
public class MyClass
{
private readonly Random random = new Random();
public static int GetRandomInt(int length)
{
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
return random.Next((int)min, (int)max);
}
}
The fact that random always returns the same values only exists for testing purposes.
Random classes usually use a seed to initialize themselves, and will usually return the same sequence provided the seed is the same one :
Always reuse the same Random() instance instead of recreating one over and over again
if you want unpredictable results, use a time-dependent seed rather than an hard-coded one
It's very difficult to code a truly random number generator. Most methods use external entropy generators (such as mouse movement, cpu temperature, or even complex physical mechanisms such as helium balloons colliding one another...).
The Random instance should be created only once and then reused. The reason for this is that the RNG is by default seeded with the current system time. If you rapidly create new Random instances (and pull one value from it) then many of them will be seeded with the same timestamp, because the loop probably executes faster than the system clock advances.
Remember, a RNG initialized by seed A will always return sequence B. So if you create three Random instances all seeded with for example 123, these three instances will always return the same number on the same iteration.

How to generate unique number of 12 digits?

I'm working on an app that sends raw data to zebra printer and print out barcodes. And since every item has its own unique barcode, I need to define a variable that automatically generates unique number of 12 digits long.
see example:
printBar prnt = new printBar("123456789012");
Is there anyway to define a double variable and pass it to a function that return uniqely 12 digits number and pass it over again to the printBar class?. But how to make sure everytime you access it returns a unique value?.
I also thought of another way, since am using MS Access db, I can create a column of AutoNumber datatype and assign it to Random, but you don't get the exact 12 digits required, sometimes it generates a value of 10 digits sometimes more or less.
Start with a twelve digit number, ie: 111111111111
to get your new 'random' unique number take the previous number and add 1.
although not random, it will guarantee uniqueness.
How many times do you generate a new barcode per day, hour, minute?
You could use a technique like the auto versioning of Visual Studio works.
Count the number of days from some specific date (e.g. 1.1.2000)
padded with 0 to five places.
Concat the seconds elapsed till midnight
padded also with zero to five places.
Fill up the last two numbers with a static counter in your App that just wrap around at 99.
Example
public static class UniqueId
{
static private int _InternalCounter = 0;
static public string Get()
{
var now = DateTime.Now;
var days = (int)(now - new DateTime(2000, 1, 1)).TotalDays;
var seconds = (int)(now - DateTime.Today).TotalSeconds;
var counter = _InternalCounter++ % 100;
return days.ToString("00000") + seconds.ToString("00000") + counter.ToString("00");
}
With this approach you'll get an overflow at the 15. October 2273, but i think this can be solved by your follower. ;-)
If you need to create more than hundred unique IDs per second you can change the last two line into:
var counter = _InternalCounter++ % 1000;
return days.ToString("0000") + seconds.ToString("00000") + counter.ToString("000");
Now you'll have thousand unique IDs per second, but the days will already overflow at 18. May 2027. If this is too short, you can get additional ten years if you set the start date to 2010 by this line:
var days = (int)(now - new DateTime(2010, 1, 1)).TotalDays;
Using an RNG and a hash do:
10 - stream out 12 digits
20 - check if value is in hash
30 - if it's goto 40 else goto 10
40 - push value into hash
50 - return new 12 digit number
60 - goto 10

Categories

Resources