Weighted random number generation C# - c#

I have been trying to search answer for this, but all discussions that I have found are either in language that I don't understand or relies on having a collection where each element has its own weight.
I want to basically just get a random number between 0 and 10, which is "middle-weighted" as in 5 comes more often than 0 and 10. Basically I have been trying to figure out an algorithm where I can give any number to be the "weighted number" between min and max values that I have defined and all the numbers generated would be weighted appropiately. I know that this may sound like "I dont want to think about this, I'll just sit back and wait someone else to do this", but I have been thinking and searching about this for like an hour and I'm really lost :|
So in the end, I want that I could call ( via extension method )
random.NextWeighted(MIN, MAX, WEIGHT);

You have an inverse normal distribution method available.
Scale your random number so that it's a double between zero and one.
Pass it to InverseNormalDistribution.
Scale the returned value based on the weight. (For example, divide by weight over 100.)
Calculate [ (MIN + MAX) / 2 ] + [ (ScaledValue) X (MAX - MIN) ]
If that's less than MIN, return MIN. If it's more than MAX, return MAX. Otherwise, return this value.

I don't know how much more often you want 5 to appear than the other numbers between 0-10 but you could create an array with the distribution you want.
Something like
var dist = new []{0,1,2,3,4,5,6,7,8,9,10,5,5,5};
Then you get a random positions of 0 and 13 you will get numbers between 0-10 but a 5 four times more often than the others. Pretty fast but not very practical if you want numbers between 0 and billion though.

Related

Transform 2 int into 1 int of 5 of lenght

This might not belong here so if I need to ask this somewhere else please tell me.
Let's say we have 10032(Will be X) and 154(Will be Y) as the input, what I would need is to get 1 int as the output. That output would also need to be of length of 4 or 5.
With the output and either X or Y know, I need to stop anyone from discovering the formula. This is a scenario where the Y will stay the same but the X will change often.
I am reading on hash but I am unsure of which one would be the best for me. Or if a simple math formula would do the job. In the program we are currently using it in the following way :
X + Y * 2 / 3 and then rounding to the lower number.
This solution would also need a very low amount of collision.
Thanks
For this question, you may have better luck at Cryptography Stack Exchange but here are a few thoughts.
It sounds like you want to map a 5-digit int and 3-digit int to a 4- or 5-digit int with the qualifications that:
a. The producing algorithm is difficult to determine given the input
b. There are few collisions
Given some function F(x,y) there are 100,000,000 combinations of x and y if x and y are between 1 and 5 digits and 1 and 3 respectively.
If F(x,y) produces a 5-digit number there are 100,000 possible solutions .
On average this would mean that each value of F(x,y) has 1,000 combinations of x, y that map to it.
So at best case this means that given x1, y1 and x2, y2 the odds that F(x1,y1)=F(x2,y2) is 1/1000, which for most uses I can think of would be considered too high.
Considering those things, probably the simplest idea would be a basic modular ring over the ints like Oscar mentioned. For your modulo you should pick the greatest prime number with the number of digits you want to keep. For instance if you want a 5 digit result use 99,877. Or if you wanted to avoid collisions and go with 9-digits, you would use 999,999,733. You can use a prime list to look up which prime you use for your modulo.
I assume that a good approach to minimise collisions would be to use modulus 10^6 after whatever operation you perform on both numbers.
The hard part would be the operation between the original ints, but look up theory about hashing and I am sure you can find nice suggestions.
In order to make it truly difficult to reverse, you could perform operations in several stages, each one of them depending on the results of the previous one. Just an idea...
decimal d = (X * Y) - (reverse X * reverse Y);
(When I say reverse 10032 would be 23001)
Then take the first 4 or 5 digits if there are more.
Or you could make a string that would look like this:
10032154 and then use a Hash method and then take the first 4 or 5 digits?
(You could reverse this too so the string is: 45123001)
BTW why do you need to take the 1st 4 or 5 digits?
Reducing the amount of digits will cause the chance of collusion to increase.

Function returning random double with exponential distribution in range (a,b)

I want to generate a random number from a to b. The problem is, the number has to be given with exponential distribution.
Here's my code:
public double getDouble(double low, double high)
{
double r;
(..some stuff..)
r = rand.NextDouble();
if (r == 0) r += 0.00001;
return (1 / -0.9) * Math.Log(1 - r) * (high - low) + low;
}
The problem is that (1 / -0.9) * Math.Log(1 - r) is not between 0 and 1, so the result won't be between a and b. Can someone help? Thanks in advance!
I missunderstood your question in the first answer :) You are already using the inversion sampling.
To map a range into another range, there is a typical mathematical approach:
f(x) = (b-a)(x - min)/(max-min) + a
where
b = upper bound of target
a = lower bound of target
min = lower bound of source
max = upper bound of source
x = the value to map
(this is linear scaling, so the distribution would be preserved)
(You can verify: If you put in min for x, it results in a, if you put in max for x, you'll get b.)
The Problem now: The exponential distribution has a maximum value of inf. So, you cannot use this equation, because it always wold be whatever / inf + 0 - so 0. (Which makes sense mathematically, but ofc. does not fit your needs)
So, the ONLY correct answer is: There is no exponential distribution possible between two fixed numbers, cause you can't map [0,inf] -> [a,b]
Therefore you need some sort of trade-off, to make your result as exponential as possible.
I wrapped my head around different possibilities out of curiosity and I found that you simple can't beat maths on this :P
However, I did some test with Excel and 1.4 Million random records:
I picked a random number as "limit" (10) and rounded the computed result to 1 decimal place. (0, 0.1, 0.2 and so on) This number I used to perform the linear transformation with an maximum of 10, ingoring any result greater than 1.
Out of 1.4 Million computations (generated it 10-20 times), only 7-10 random numbers greater than 1 have been generated:
(Probability density function, After mapping the values: Column 100 := 1, Column 0 := 0)
So:
Map the values to [0,1], using the linear approach mentioned above, assume a maximum of 10 for the transformation.
If you encounter a value > 1 after the transformation - just draw another random number, until the value is < 1.
With only 7-10 occurences out of 1.4 Million tests, this should be close enough, since the re-drawn number will again be pseudo-exponential-distributed.
If you want to build a spaceship, where navigation depends on perfectly exponential distributed numbers between 0 and 1 - don't do it, else you should be good.
(If you want to cheat a bit: If you encounter a number > 1, just find the record that has the biggest variance (i.e. Max(occurrences < expected occurrences)) from it's expected value - then assume that value :P )
Since the support for the exponential distribution is 0 to infinity, regardless of the rate, I'm going to assume that you're asking for an exponential that's truncated below a and above b. Another way of expressing this would be an exponential random variable X conditioned on a <= X <= b.
You can derive the inversion algorithm for this by calculating the cumulative distribution function (CDF) of the truncated distribution as the integral from a to x of the density for your exponential. Scale the result by the area between a and b (which is F(b) - F(a) where F(x) is the CDF of the original exponential distribution) to make it a valid distribution with an area of 1. Set the derived CDF to U, a uniform(0,1) random number, and solve for X to get the inversion.
I don't program C#, but here's the result expressed in Ruby. It should translate pretty transparently.
def exp_in_range(a, b, rate = 1.0)
exp_rate_a = Math.exp(-rate * a)
return -Math.log(exp_rate_a - rand * (exp_rate_a - Math.exp(-rate * b))) / rate
end
I put a default rate of 1.0 since you didn't specify, but clearly you can override that. rand is Ruby's built-in uniform generator. I think the rest is pretty self-explanatory. I cranked out several test sets of 100k observations for a variety of (a,b) values, loaded the results into my favorite stats package, and the results are as expected.
The exponential distribution is not limited on the positive side, so values can go from 0 to inf. There are many ways to scale [0,infinity] to some finite interval, but the result would not be exponential distributed.
If you just want a slice of the exponential distribution between a and b, you could simply draw r from [ra rb] such that -log(1-ra)=a and -log(1-rb)=b , i,e,
r=rand.NextDouble(); // assume this is between 0 and 1
ra=Math.Exp(-a)-1;
rb=Math.Exp(-b)-1;
rbound=ra+(rb-ra)*r;
return -Math.Log(1 - rbound);
Why check for r==0? I think you would want to check for the argument of the log to be >0, so check for r (or rbound int this case) ==1.
Also not clear why the (1/-.9) factor??

Dividing a number and display a remainder in C#

Hi I am currently teaching myself C# using different books and online solutions, there is one exercise that i cant really get my head around. I had to divide a number by another number in C# using iteration and subtraction but the remainder had to be displayed at the end. I figured out that I could use a while loop to keep dividing one number by the other (lets say 400 / 18) but how to display the decimal at the end from the int number was the part I could not get my head around.
Any help would be greatly appriciated :)
So let's think about this outside the C# language. Because this is really just a math problem to solve.
If you've got 400/18, and you are going to use iteration and subtraction, all you are doing is saying "how many times can I subtract 18 from 400?", right?
So that's going to look something like this:
remainder = 400
value = 18
while (remainder > value)
remainder = remainder - value
Once you exit that while loop, you've got your remainder.
You could use the modulus operator "%" to solve this in one step but based on what you wrote, this is what you would do.
The remainder you've got is can be expressed as so:
double theDecimalValue = (double)remainder/value;
Assuming you were dealing with integers, you'd just cast the remainder value to avoid the truncating integer division that will take place otherwise.
if you need the remainder the easy and right way is
int reminder = 400%18;
if you HAVE TO using a loop you have to :
check if number is less than the divisor or whatever it's called
2a.if yes exit from the loop and show the number
2b if not remove divisor from number and go on next iteration

Hash function for comparison

Well I am wondering normally hash function create an unique number.
Are there also hash functions that can be used for approximately comparisons?
so for example
6 7 8 9 10 11 23 40 10
5 8 10 9 9 12 24 40 20 would match
25 7 12 9 10 12 90 90 would not match
I am wondering this because I'm thinking about pattern recognition. I wonder if there is some math for which one could give a percentage of match you like to find. Using C# as a programing language.
Some clarification, first let me explain a synonym of what i like to catch.
Imagine water droplets fall down but its not in a constant flow.
Measurement tools are also not perfect. So now i am timing the difference between droplets faling down, this is a measurement of a series, say between 19 and 25 droplets in fact i can measure at once such a series for example if i had camera and filmed it.
Now i like to figure out having this "series" when next series starts is it different or is it the same, there might be a random gap of time between series, and the measure ment tools dont detect beginning or end of a series, they just take in between 19 or 25 measurements at once.
I'm not sure in which direction to go with this, maybe fuzzie logic, neural network patern detection, distance vectors.. there seams to lots of ways, but i wonder would be something more simple (i was thinking of something like an hash, but maybe it should be something else).
Hash functions can be used for (not uniquely) identifying certain values. They are not guaranteed to be unique (better said, it is guaranteed that some different values will have identical hash codes). A small deviation in the value usualy results in a completely different hash code (As #Bobson already has mentioned.) Another use of hash codes is to find in-equality of two values in constant time.
It might be possible to design a hash code function that will do what you want, specialy if you know the domain your values are living in. But that will need a mathematical background to do.
As far as I know there is no hash function for the example you gave.
Here is another idea for integers, use modulo 10 operations and calculate the absolute difference betweeen each digit. This way you calculate the 'distance' between two number, not the 'difference'. I did something similar once on strings to find strings close to each other.
Some pseudo code:
int Distance(int x, int y)
{
int result = 0;
while ((x > 0) && (y > 0))
{
result += abs(x%10 - y%10);
x /= 10;
y /= 10;
}
return result;
}
void Caller()
{
int distance = Distance(123, 456);
if (distance == 0) write("x and y are equal");
else write("the relative distance between x and y = " + distance.ToString())'
}

How to manage AI actions based on percentages

I am looking now for some time about how can a programmer simulate a AI decision based on percentages of actions for the final fantasy tactic-like games (strategy game).
Say for example that the AI character has the following actions:
Attack 1: 10%
Attack 2: 9%
Magic : 4%
Move : 1%
All of this is far from equaling 100%
Now at first I though about having an array with 100 empty slots, attack would have 10 slots, attack 2 9 slots on the array. Combining random I could get the action to do then. My problem here is it is not really efficient, or doesn't seem to be. Also important thing, what do I do if I get on an empty slot. Do I have to calculate for each character all actions based on 100% or define maybe a "default" action for everyone ?
Or maybe there is a more efficient way to see all of this ? I think that percentage is the easiest way to implement an AI.
The best answer I can come up with is to make a list of all the possible moves you want the character to have, give each a relative value, then scale all of them to total 100%.
EDIT:
For example, here are three moves I have. I want attack and magic to be equally likely, and fleeing to be half as likely as attacking or using magic:
attack = 20
magic = 20
flee = 10
This adds up to 50, so dividing each by this total gives me a fractional value (multiply by 100 for percentage):
attack = 0.4
magic = 0.4
flee = 0.2
Then, I would make from this a list of cumulative values (i.e. each entry is a sum of that entry and all that came before it):
attack = 0.4
magic = 0.8
flee = 1
Now, generate a random number between 0 and 1 and find the first entry in the list that is greater than or equal to that number. That is the move you make.
No, you just create threshholds. One simple way is:
0 - 9 -> Attack1
10 - 18 -> Attack 2
19 - 22 -> Magic
23 -> Move
Something else -> 24-99 (you need to add up to 100)
Now create a random number and mod it by 100 (so num = randomNumber % 100) to define your action. The better the random number to close to a proper distribution you will get. So you take the result and see which category it falls into. You can actually make this even more efficient but it is a good start.
Well if they don't all add up to 100 they aren't really percentages. This doesnt matter though. you just need to figure out the relative probability of each action. To do this use the following formula...
prob = value_of_action / total_value_of_all_actions
This gives you a number between 0 and 1. if you really want a percentage rather than a fraction, multiply it by 100.
here is an example:
prob_attack = 10 / (10 + 9 + 4 + 1)
= 10 / 24
= 0.4167
This equates to attack being chosen 41.67% of the time.
you can then generate thresholds as is mentioned in other answers. And use a random number between 0 and 1 to choose your action.

Categories