0

Requirement: generate 10k of unique numbers composed of a sequential number (16 digits) followed by a random numeric string (4 digits). Weapon of choice is Powershell because it's the only tool I have a very limited knowledge of.

Problems encountered:

  1. Generating 10k sequential numbers using the following method: 1400000000000000..1400000000010000 and putting into a variable. Error: Value is to large for an Int32
  2. Generating 10k of 4 digit via Get-Random -Minimum 0001 -Maximum 9999 and putting them in a variable. I manage only to obtain 1 random number.
  3. Combining the two variables using the Join-Object (or at least that's what I hope could be done)

How can I combine these 3 commands to obtain a list of semi random numbers as specified above? Or is there simpler way to achieve the same result?

knuckle_sandwich
  • 77
  • 1
  • 3
  • 11

4 Answers4

3
(0..10000).ForEach{ '14000000000{0:00000}{1:0000}' -f $_, (Get-Random 10000) }

Result:

14000000000000004965
14000000000000010114
14000000000000026382
14000000000000038644
14000000000000045435
14000000000000052051
14000000000000061801
14000000000000077046
14000000000000087791
14000000000000098090
14000000000000102712
....

Explanation:

  • Use the Format Operator (-f) to format the string, like '14000000000{0:00000}{1:0000}'. For details, see composite formatting.
  • You do not have to put the whole 16 digit number in a [int32], just count from 0..1000 with leading zeros up to 5 digits ({0:00000}) and prefix it with 14000000000
  • In the second place holder ({1:0000}), place a new random number with leading zeros up to 4 digits
iRon
  • 11,580
  • 4
  • 35
  • 54
1

iRon's answer provides an elegant solution.

Let me complement it by addressing points 1. and 2. individually:

Re 1.

.., the range operator supports only [int] (System.Int32) (numeric) endpoints (incidentally, the same applies to LINQ's Range method).

You can use the .ForEach() array method to work around the problem, as also shown in iRon's answer.

# Returns a collection of [long] (System.Int64) values.
(0..10000).ForEach({ 1400000000000000 + $_ })

Re 2.

PowerShell [Core] now supports a -Count parameter for Get-Random that allows you to request a given number of random numbers between the specified bounds.

# PowerShell [Core] only
# Note that there's no point in specifying leading zeros (0001).
# The output will be an array of unformatted [int] (System.Int32) values
$10kRandomNums = Get-Random -Count 10000 -Minimum 1 -Maximum 9999

Note: The -Maximum value (unlike -Minimum) is non-inclusive; that is, the highest random number that can be returned is 1 lower, 9998.

In Windows PowerShell, you'll have to call Get-Random in a loop:

# Windows PowerShell
$10kRandomNums = foreach ($i in 1..10000) { Get-Random -Minimum 1 -Maximum 9999 }

Calling a cmdlet in a loop is expensive; you can speed things up noticeably by using the System.Random .NET class directly:

$rnd = [Random]::new()
$10kRandomNums = foreach ($i in 1..10000) { $rnd.Next(1, 9999) }
mklement0
  • 245,023
  • 45
  • 419
  • 492
0

The classic algorithm for creating an unique sequence is to put all the values into an array. Pick a value. Move the last value of the array into the place from where you just picked the value. Then decrease the array's size by one. This creates a copy of the array, so if there are lots of values, be wary of the extra cost that is caused by resizing an array.

An example that shuffles values from 0 to 19 is like so,

$rnd = @()
$arr = 0..19
$tail = $arr.Length-1

do {
    $pick = get-random -min 0 -max $tail
    $rnd += $arr[$pick]
    $arr[$pick] = $arr[$tail]

    $tail--
} while($tail -gt 0)
$rnd += $arr[0]
# Uncomment the next statement to print shuffled array
# $rnd -join ', '

Since the value doesn't fit into int32, use int64. To add the shuffled values, a loop works like so,

$big = @()
$seed = [int64]1400000000000000

$rnd | % {
  $big += $seed + $_
}
$big

Output

PS C:\> $big
1400000000000015
1400000000000006
1400000000000010
1400000000000017
1400000000000009
1400000000000004
1400000000000005
1400000000000016
1400000000000014
1400000000000003
1400000000000001
1400000000000002
1400000000000013
1400000000000011
1400000000000012
1400000000000019
1400000000000000
1400000000000007
1400000000000008
1400000000000018
vonPryz
  • 19,131
  • 6
  • 48
  • 56
0

Similar to elegant and accepted iRon's answer here is a way to generate 26 digit serial number that is suitable for SMBIOS or chasis serial number (for example when creating virtual machine):

"{0:####-####-####-####}-{1:####-####-##}" -f (Get-Random -Minimum 1000000000000000 -Maximum 9999999999999999),(Get-Random -Minimum 1000000000 -Maximum 9999999999)

And sample output results like this:

5682-4527-3132-4212-5548-2660-46
6433-6848-9306-5822-1601-7101-98
6986-6609-3112-9326-3662-7689-92

References

Stritof
  • 720
  • 6
  • 10