linear probability from non-linear one - algorithm

here is my problem.
Imagine you've got a function like that : (here in C )
int strangeRand() {
if ( rand() % 100 <= 70 ) return 0;
else return 1;
}
This one return 0 a probability of 0.7
and 1 with a probability of 0.3
Here is what i want to do, create a function that return 0 with a probability of 0.5 and 1 with a probability of 0.5 too.
I need to only use strangeRand() function [Can't modify it] (and loop, and if etc but no rand() function )
Is someone got an idea, how to do this ?
Thanks.

This is actually a solved problem! It's usually known as getting a fair result from an unfair coin.
The algorithm works as follows:
Call the function twice.
If the results match, start over, forgetting both results.
If the results differ, use the first result, forgetting the second.
The provided link contains an explanation of why the algorithm works.

Related

Finding the exp

Hi I have a question on the result of the following function
The input is the row vector of x and we are outputing the calculated exp value using the ∑_(n=0)^(n=50)▒(x^n)/n! (i.e. Summation from n=0 to n=50 using x^n)/n!)
The loop will terminate either when n reaches 50 or (x^n)/n! < 0.01
function [summ] = ExpFunction(x)
// there is a loop to iterate.
There are two versions
1) We write an if to see if the value (x^n)/n! is >= 0.01. if it is then add it the the summ.
2) Add it to the summ first and then check if (x^n)/n! is >= 0.01. if not then terminates the program.
My question is that why do the two versions produce different results and the second version appears to produce better results(i.e. closer the exp(x) )
Thank you
version 1:
function [result] = Exp(x)
result = 0;
a = 0;
n = 0;
while(n <= 50)
{
a = (x.^n)/factorial(n) %% The factorial function is self written have have been checked.
if(abs(a) >= 0.01)
result = result + a;
else
break;
n = n + 1;
}
Second version is to do result = result + a; before checking abs(a) >=0.01
The question seems simple. The series is increasing (i.e. each addition results in a larger sum) and the limit value is being approached from below. This means that every new term added to the sum is getting closer to the final value = the limit. This results in each addition being a better approximation to the result.
It is also clear that the first method, not adding the term, will result in a slightly less accurate result than the second method, which does add the term.
It is clear that the accuracy of the result is improved by adding more terms. The only cost is the extra computing time. Is your termination criterion (x^n/factorial(n) < 0.01) giving good enough values for all values of x? I would have expected you to use a formula more like (x^n/factorial(n) < g(x)) where g(x) is a formula involving x. I suggest that you go back to the text on series and determine whether a better g(x) is required for your accuracy requirements.

How map/tween a number based on a dynamic curve

I am really lacking terminology here, so any help with that appreciate. Even it doesn't answer the question it can hopefully get me closer to an answer.
How can I get y from a function of p where the curviness is also a variable (possible between 0 and 1? Or whatever is best?).
I am presuming p is always between 1 and 0, as is the output y.
The graphic is just an illustration, I don't need that exact curve but something close to this idea.
Pseudo code is good enough as an answer or something c-style (c, javascript, etc).
To give a little context, I have a mapping function where one parameter can be the – what I have called – easing function. There are based on the penner equations. So, for example if I wanted to do a easeIn I would provide:
function (p) { return p * p; };
But I would love to be able to do what is in the images: varying the ease dynamically. With a function like:
function (p, curviness) { return /* something */; }
You might try messing around with a Superellipse, it seems to have the shape malleability you're looking for. (Special case: Squircle)
Update
Ok, so the equation for the superellipse is as follows:
abs(x/a)^n + abs(y/b)^n = 1
You're going to be working in the range from [0,1] in both so we can discard the absolute values.
The a and b are for the major and minor ellipse axes; we're going to set those to 1 (so that the superellipse only stretches to +/-1 in either direction) and only look at the first quadrant ([0, 1], again).
This leaves us with:
x^n + y^n = 1
You want your end function to look something like:
y = f(p, n)
so we need to get things into that form (solve for y).
Your initial thought on what to do next was correct (but the variables were switched):
y^n = 1 - p^n
substituting your variable p for x.
Now, initially I'd thought of trying to use a log to isolate y, but that would mean we'd have to take log_y on both sides which would not isolate it. Instead, we can take the nth root to cancel the n, thus isolating y:
y = nthRoot(n, 1 - p^n)
If this is confusing, then this might help: square rooting is just raising to a power of 1/2, so if you took a square root of x you'd have:
sqrt(x) == x^(1/2)
and what we did was take the nth root, meaning that we raised things to the 1/n power, which cancels the nth power the y had since you'd be multiplying them:
(y^n)^(1/n) == y^(n * 1/n) == y^1 == y
Thus we can write things as
y = (1 - p^n)^(1/n)
to make things look better.
So, now we have an equation in the form
y = f(p, n)
but we're not done yet: this equation was working with values in the first quadrant of the superellipse; this quadrant's graph looks different from what you wanted -- you wanted what appeared in the second quadrant, only shifted over.
We can rectify this by inverting the graph in the first quadrant. We'll do this by subtracting it from 1. Thus, the final equation will be:
y = 1 - (1 - p^n)^(1/n)
which works just fine by my TI-83's reckoning.
Note: In the Wikipedia article, they mention that when n is between 0 and 1 then the curve will be bowed down/in, when n is equal to 1 you get a straight line, and when n is greater than 1 then it will be bowed out. However, since we're subtracting things from 1, this behavior is reversed! (So 0 thru 1 means it's bowed out, and greater than 1 means it's bowed in).
And there you have it -- I hope that's what you were looking for :)
Your curviness property is the exponent.
function(p, exp) { return Math.pow(p, exp); }
exp = 1 gives you the straight line
exp > 1 gives you the exponential lines (bottom two)
0 < exp < 1 gives you the logarithmic lines (top two)
To get "matching" curviness above and below, an exp = 2 would match an exp = 1/2 across the linear dividing line, so you could define a "curviness" function that makes it more intuitive for you.
function curvyInterpolator(p, curviness) {
curviness = curviness > 0 ? curviness : 1/(-curviness);
return Math.pow(p, curviness);
}

How to make this algorithm stable

I have to compute the iterative version of this formula:
f(i)=integral ( x^i/(4x+1) ) from 0 to 1
Using these formulas:
f(0)=ln(5)/4;
f(i)=1/(i+1) - 4*f(i+1);
I have tried tried the following: I calculate integral ( x^100/(4x+1) ) from 0 to 1, and store the result.Then I calculate f(i) starting from this result, using the iterative version.
But I get wrong result because the error is too big.
The error is acceptable only for i<=25.
I would like to know, why this algorithm is not stable and if there's a solution to compute the result starting from i=100 or higher.
This is the code:
function y=Integral(i,max)
if i==0
y=1/4*log(5);
elseif i==max
y=0.0;
else
y=1/(i+1)-4*Integral(i+1,max);
end
end
With this function I never get an exact value because the error accumulated is too high.I get a close value (but even 3 or 4 times higher, so not acceptable) if I use i=15 and max=18.I need the stable version of this formula.
This recursive function should do the job without the need to store partial results on the way to 100:
function y = Integral(i)
if i==0
y=log(5)/4;
else
y = (-Integral(i-1) + 1/i)/4;
end
end
For recursion to work you need to start from i=100 and then call the function with i-1 until it reaches i=0.
Integral(100) will give the final answer without the need to store partial results.

Will this algorithm terminate?

With different values in a collection, will this algorithm (pseudeocode) ever terminate?
while (curElement != average(allElements))
{
curElement = average(allElements);
nextElement();
}
Note that I'm assuming that we will re-start from the beginning if we're at the end of the array.
Since this is pseudocode, a simple example with 2 elements will reveal that there are cases where the program won't terminate:
x = 0, y = 1;
x y
Step 1: 0.5 1
Step 2: 0.5 0.75
Step 3: 0.635 0.75
//and so one
With some math involved, lim(x-y) = lim( 1 / 2^n )
So the numbers converge, but they're never equal.
However, if you'd actually implement this on a computer, they will turn out equal because of hardware limitations - not all numbers can be expressed in a limited number of bits.
It depends.
If your elements hold discrete values, then most likely they will fall into the same value after a few runs.
If your elements hold limited precision values (such as floats or doubles), then it will take longer, but finite time.
If your elements hold arbitrary precision values, then your algorithm may never finish. (If you count up every piece of an integral and add it to a figure you have on a piece of paper, you need infinite time, an infinitely large piece of paper, and infinite patience with this analogy.)
There is little difference between your code and the following:
var i = 1;
while (i != 0)
i = i / 2;
Will it ever terminate? That really depends on the implementation.

How to compute the "15% of the time" randomness?

I'm looking for a decent, elegant method of calculating this simple logic.
Right now I can't think of one, it's spinning my head.
I am required to do some action only 15% of the time.
I'm used to "50% of the time" where I just mod the milliseconds of the current time and see if it's odd or even, but I don't think that's elegant.
How would I elegantly calculate "15% of the time"? Random number generator maybe?
Pseudo-code or any language are welcome.
Hope this is not subjective, since I'm looking for the "smartest" short-hand method of doing that.
Thanks.
Solution 1 (double)
get a random double between 0 and 1 (whatever language you use, there must be such a function)
do the action only if it is smaller than 0.15
Solution 2 (int)
You can also achieve this by creating a random int and see if it is dividable to 6 or 7. UPDATE --> This is not optimal.
You can produce a random number between 0 and 99, and check if it's less than 15:
if (rnd.Next(100) < 15) ...
You can also reduce the numbers, as 15/100 is the same as 3/20:
if (rnd.Next(20) < 3) ...
Random number generator would give you the best randomness. Generate a random between 0 and 1, test for < 0.15.
Using the time like that isn't true random, as it's influenced by processing time. If a task takes less than 1 millisecond to run, then the next random choice will be the same one.
That said, if you do want to use the millisecond-based method, do milliseconds % 20 < 3.
Just use a PRNG. Like always, it's a performance v. accuracy trade-off. I think making your own doing directly off the time is a waste of time (pun intended). You'll probably get biasing effects even worse than a run of the mill linear congruential generator.
In Java, I would use nextInt:
myRNG.nextInt(100) < 15
Or (mostly) equivalently:
myRNG.nextInt(20) < 3
There are way to get a random integer in other languages (multiple ways actually, depending how accurate it has to be).
Using modulo arithmetic you can easily do something every Xth run like so
(6 will give you ruthly 15%
if( microtime() % 6 === ) do it
other thing:
if(rand(0,1) >= 0.15) do it
boolean array[100] = {true:first 15, false:rest};
shuffle(array);
while(array.size > 0)
{
// pop first element of the array.
if(element == true)
do_action();
else
do_something_else();
}
// redo the whole thing again when no elements are left.
Here's one approach that combines randomness and a guarantee that eventually you get a positive outcome in a predictable range:
Have a target (15 in your case), a counter (initialized to 0), and a flag (initialized to false).
Accept a request.
If the counter is 15, reset the counter and the flag.
If the flag is true, return negative outcome.
Get a random true or false based on one of the methods described in other answers, but use a probability of 1/(15-counter).
Increment counter
If result is true, set flag to true and return a positive outcome. Else return a negative outcome.
Accept next request
This means that the first request has probability of 1/15 of return positive, but by the 15th request, if no positive result has been returned, there's a probability of 1/1 of a positive result.
This quote is from a great article about how to use a random number generator:
Note: Do NOT use
y = rand() % M;
as this focuses on the lower bits of
rand(). For linear congruential random
number generators, which rand() often
is, the lower bytes are much less
random than the higher bytes. In fact
the lowest bit cycles between 0 and 1.
Thus rand() may cycle between even and
odd (try it out). Note rand() does not
have to be a linear congruential
random number generator. It's
perfectly permissible for it to be
something better which does not have
this problem.
and it contains formulas and pseudo-code for
r = [0,1) = {r: 0 <= r < 1} real
x = [0,M) = {x: 0 <= x < M} real
y = [0,M) = {y: 0 <= y < M} integer
z = [1,M] = {z: 1 <= z <= M} integer

Resources