FreqTable with random values(#C) - c#

I would like to make a frequency table with random numbers.
So i have created a array that generates 11 random values between 0 and 9999.
public void FillArrayRandom(int[] T)
{
Random Rndint = new Random();
for (int i=0; i < T.Length; i++)
{
T[i] = Rndint.Next(0, 9999);
}
}/*FillArrayRandom*/
The result i want is something alike this:(bar height up to 21) So this will be a constant.
*
* *
* * * (the highest value will have the largest row/bar)
* * * *
0 1 2 3 .....(index value's)
931 6669 10 8899 .... (up to 11 random values)
My question is how do i exactly caculate the frequency between those 11 random values?
The bars should have a relative relation with each other depending on there frequency.
I would only like to use 1 single array in my program (for the generated values).
F = (F * 21?) / ...? Really no clue how to obtain the proper results.
If a frequency is >=21 write * If a frequency is >=20 write * If a frequency is >=19 write * , and so on until i reach 1. (and the full table is displayed
Basicly i would like to print the table line per line with consolewrite(line).
etc...
Regards.

To calculate frequency you could use a Dictionary defined something like:
freqDict Dictionary<int, int> = new Dictionary<int, int>();
Where the first integer (K) is the key that corresponds to your random value or its index in the values array, either way it has to be unique and able to reference to a particular value. The second integer is the value (V) that is your count of each key.
Next, walk your array of randomly generated values and if it's not represented in the dictionary add it with the new key and set the value to 1. If the dictionary already contains the key you simply increment the value by 1. Do this for each value in your rand array and you will have a dictionary with a frequency distribution.

Related

Finding All Combinations of a Multidimention Array with a Max Value in C#

Let's say I have an int[8,6] array which can have the maximum value of 255 per cell and I want to find all combinations of this array.
What is the most efficient way to accomplish this?
For array size N (1D array for simpliciry, 2D case works similar) and maximum value M there are M^N possible combinations. Every combination corresponds to value in range 0..M^N-1, so we can just walk throug this range and get combination for every value. Of course, it is possible for reasonable small values of N and M.
Python-like pseudocode:
int A[N]
P = M**N #math.intpower(M, N)
for i in range(P):
t = i
for k in range(N): #number of cells, number of digits in counter value
A[k] = t % M # value in k-th cells of result for variant number i
t = t // M #integer division
Note that for base M=256 you perhaps don't need to use division - needed values are just bytes of multibyte representation of big number in base 256

prefer high index number than lower one in an array

Assuming that I have these two sorted arrays with 5 cells:
The numbers in the array are between 2 and 14 ( 2 and 14 included and they are integers )
Now, I need to give a rank to each array from [0,100] when the lowest array will be:
[2,2,2,2,2] and the highest will be [14,14,14,14,14]
Now the thing is: the index is important so for example if we take a look at this these arrays:
1) [2,2,2,2,10]
2) [8,8,8,8,9]
So the 1st one is better than the the 2nd and will get an higher score.
And if there's a tie in the index ( from right to left ) for example:
1) [3,4,5,10,13]
2) [3,4,7,10,13]
So index numbers: 3 and 4 are the same, but since 7 is higher than 5. so in that case the 2nd array will have an higher score.
I'm struggling with the math, I mean I want to do it efficient, now I can do something like:
2^array[i] but it won't be efficient, so the main thing I managed to do is
double rank = 0;
for (int i = 0; i < 5; i++)
{
rank += (double)array[i] / 14 + i;
}
because if array[i] can be between 2 and 14, so 1/7 <= array[i]/14 <= 1
so I thought that if I'll add + i each iteration, the next iteration will be greater than all the previous ones, but it's mistake.
I'll be glad for some help in here.
You are essentially describing a base-13 number. Each "digit" (array position) represents one of 13 distinct, ordered values.
You can calculate a ranking by converting the array to a 5 digit, base 13 value:
Subtract 2 from each array element's value to normalize the element value to the range 0..12.
Give each array element a score = (normalized element value) * (13 raised to the array index power). 1)
Add up the scores.
1) Or raised to Array.Length - array index, depending on which side of the array should be the least significant.

generate seemingly random unique numeric ID in SQL Server

I need to use SQL Server to generate seemingly random unique 8-digit numeric ID (can pad zeros at front). Is there a built-in functionality for this? I saw this Identity property, but it is sequential, not random.
If this is not possible, is it good practice to directly write a randomly generated ID to db then check for exception? (note that my app is multi-threaded, so checking before writing doesn't guarantee uniqueness unless done in atomic action.)
Thanks!
UPDATE: Added "numeric" to clarify.
Edited to show that the randomness doesn't need to be cryptographically strong or anything near. Just seemingly random is good enough. Oliver suggested an elegant solution, and I've posted an answer using that approach. Thanks, Oliver!
Randomness clashes with uniqueness, but there is an elegant solution suggested by #Oliver when the numbers only need to appear random, while an underlying order exists. From Erics' http://ericlippert.com/2013/11/14/a-practical-use-of-multiplicative-inverses/, the main idea is that for given a pair of coprime, positive integers x and m, we can find a multiplicative inverse y where (x*y) % m == 1. This is very useful because given a database row ID z, we can map z to another integer by doing encoded = (z*x) % m. Now given this encoded, how can we get z back? Simple, z = (encoded * y) % m since (x*y*z) % m == z given z < m. This one-to-one correspondence guarantees uniqueness of the "encoded" while provides an apparance of randomness.
Note that Eric showed how to calculate this multiplicative inverse. But if you are lazy, there is this.
In my implementation, I just store the sequential ID of each row as it is. Then, each ID is mapped to another number, something simlar to the "InvoiceNumber" in the article. When the customer hands you back this "InvoiceNumber", you can map it back to its original database ID by using multiplicative inverse.
Below is a C# example of encoding and decoding sequence from 0 to 9.
public static void SeeminglyRandomSequence()
{ //use long to prevent overflow
long m = 10; //modulo, choose m to be much larger than number of rows
long x = 7; //anything coprime to m
long y = 3; //multiplicative inverse of x, where (y*x) % m == 1
List<long> encodedSequence = new List<long>();
List<long> decodedSequence = new List<long>();
for (long i = 0; i < m; i++)
{
long encoded = (i * x) % m;
encodedSequence.Add(encoded);
}
foreach (long encoded in encodedSequence)
{
long decoded = (encoded * y) % m;
decodedSequence.Add(decoded);
}
Debug.WriteLine("just encoded sequence from 0 to {0}. Result shown below:", (m - 1));
Debug.WriteLine("encoded sequence: " + string.Join(" ", encodedSequence));
Debug.WriteLine("decoded sequence: " + string.Join(" ", decodedSequence));
}
The printed result is:
just encoded sequence from 0 to 9. Result shown below:
encoded sequence: 0 7 4 1 8 5 2 9 6 3
decoded sequence: 0 1 2 3 4 5 6 7 8 9
As you can see, each input is mapped to a unique output, and it's easy to reverse this mapping. In your application, you might want to start with 1 since 0 always maps to itself.
Just to show the "apparent randomness" for larger m, below are the first 10 mappings when m=100,000,000:
just encoded sequence from 1 to 10. Result shown below:
encoded sequence: 81654327 63308654 44962981 26617308 8271635 89925962 71580289 53234616 34888943 16543270
decoded sequence: 1 2 3 4 5 6 7 8 9 10
USE the below query to create 8 digit randow unique number.
SELECT CAST(RAND() * 100000000 AS INT) AS [RandomNumber]
To avoid exception while inserting of existing number into DB use below query.
IF NOT EXIST(SELECT UniqueColumnID FROM TABLENAME WHERE UniqueColumnID = #RandowNumber)
BEGIN
--Insert query using #RandowNumber.
END
you can use NEWID() to generate uniqueIdentifier data which always random and unique each time
To get 8 character you can use substring, left etc function.
select substring( cast( NEWID() as varchar(100)),0,8)
or new logic for uniqueness:- http://forums.asp.net/t/1474299.aspx?How+to+generate+unique+key+of+fixed+length+20+digit+in+sql+server+2005+
select Left(NewID(),4)+Right(NewId(),4)
you can use random() function for this too.
check this links:
How do I generate random number for each row in a TSQL Select?
How to get numeric random uniqueid in SQL Server
Updated
If you want to unique value int data-type and 8 character long. Good to make a identity column like below, which is good for 8 character length data means (10,000,000). But after that it gives you exception. So be carefull which logic you want.(Still I say, its bad idea). store as random value as above with more length so uniqueness comes.
create table temp (id numeric(8,0) IDENTITY(1,1) NOT NULL, value1 varchar ) --if you want do not stop after 8 character , give int datatype.
insert into temp values( 'a'), ('b'), ('c')
select * from temp
drop table temp
Finally
It's not guaranteed unique but it's hard to get duplicates with NEWID()(refer above link forums.asp.net)
Create a SQL function or procedure as follow:
ALTER FUNCTION [dbo].[GenerateRandomNo]
(
#Lower INT = 111111111,
#Upper INT = 999999999
)
RETURNS NVARCHAR(128)
AS
BEGIN
DECLARE #TempRandom FLOAT
DECLARE #Random NVARCHAR(128);
-- Add the T-SQL statements to compute the return value here
SELECT #TempRandom = RandomNo from RandomNo
SELECT #Random = CONVERT(NVARCHAR(128),CONVERT(INT,ROUND(((#Upper - #Lower -1) * #TempRandom + #Lower), 0)))
WHILE EXISTS(SELECT * FROM Table WHERE Column = #Random)
BEGIN
SELECT #TempRandom = RandomNo from RandomNo
SELECT #Random = CONVERT(NVARCHAR(128),CONVERT(INT, ROUND(((#Upper - #Lower -1) * #TempRandom + #Lower), 0)))
END
-- Return the result of the function
RETURN #Random
END
And then call that function passing parameter if you want to generate random no with specific length or range.
--create
-- table Tbl( idx int)
DECLARE
#unique_id int
SET #unique_id= ( SELECT ROUND( 89999999 * RAND(
) + 10000000 , 0
)
)
IF not EXISTS( SELECT idx
FROM tbl
WHERE idx = #unique_id
)
BEGIN
INSERT INTO tbl( idx
)
VALUES( #unique_id
)
SELECT #unique_id, * FROM tbl
END;
--TRUNCATE TABLE tbl

Selecting a number from natural number < n excluding a possibility

Given n natural number starts from 0, and b which is a number in between 0 to n
I wish to randomly select a number excluding b.
Say n is 5
then The number to be selected is {0,1,2,3,4,5}
say b is 4,
then my random selection is from {0,1,2,3,5}
A way to do this is to do a while loop, until the random.nextInteger() does not find a 4.
Is there a easy to to do this other than using a while loop?
I would write a simple extension:
// N.B. : min is inclusive, max is exclusive; so range is: [min,max) - {toExclude}
public static int Next(this Random rand, int min, int max, int toExclude)
{
int v = rand.Next(min, max - 1);
if (v < toExclude)
return v;
return v + 1;
}
Usage:
var random = new Random();
var val = random.Next(0,6,4); // 6 because max is exclusive in C# random.Next()
Your approach is the best in my optinion. It is simple and elegant, and even for m=2 it is O(1) on average (The expected number of redraws is 1/2 + 1/4 + 1/8 + .... < 1).
If you want to avoid the worst case of infinite loop there is an alternative, though I doubt it will have real performance impact.
draw a random double in range [0,1]. let it be d. If d < b/m: draw a number in range [0,b) and return it.
Else (d > b/m) - draw a random number in range [b+1,m] and return it.
Note, it is indeed uniform distributed because:
There are m+1 numbers in range 0,...,m, but only m "valid" numbers (excluding b).
There are b numbers in range 0,1,...,b-1 - so the probability of the number being in this range assuming uniform distribution is b/m - which is exactly P(d < b/m).
In java it will look similar to this:
int m = 5, b = 4;
Random r = new Random();
double d = r.nextDouble();
if (d < ((double)b)/m) {
System.out.println(r.nextInt(b));
} else {
System.out.println(r.nextInt(m-b) + b + 1);
}
Here is another approach if you prefer:
import random
def random_unifrom(n,b):
assert b < n and n > 0 and b > 0
nMinusOneList = [i for i in range(n) if i != b]
lSize = len(nMinusOneList)
randIndex = random.randint(0, lSize-1)
return nMinusOneList[randIndex]
I wrote this in python just for simplicity.
creating the nMinusOneList has complexity of O(n).
returning the random index complexity depends on the random function you are using.
At the end, you loose nothing if you take this approach instead of a while loop, but even if you use the while loop approach, if the random function is random (!!) then you should not have a problem. However, my approach above excludes the number you do not need from the very beginning.
In C#, the one line I use in python might be a couple of lines which consists of a for loop on the range 0 to n, with a condition that the x (for loop index) does not equal to b, in building the list, and then you will have the list that excludes b.

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.

Categories

Resources