Random Number Generator - java

I need to write a program in Java to generate random numbers within the range [0,1] using the formula:
Xi = (aXi-1 + b) mod m
assuming any fixed int values of a, b & m and X0 = 0.5 (ie i=0)
How do I go about doing this?
i tried doing this but it's obviously wrong:
int a = 25173, b = 13849, m = 32768;
double X_[i];
for (int i = 1; i<100; i++)
X_[i] = (a*(X_[i]-1) + b) % m;
double X_[0] = 0.5;
double double = new double();
System.out.println [new double];

Here are some hints:
int a, d, m, x;
Multiplication is * and mod is %.
update
Okay, I'll give you a little more of a hint. You only need one X, you don't need all these arrays; since you're only using integers you don't need any floats or doublts.
The important line of code will be
x = (a * x + b) % m ;
You don't need another x there because the x on the right hand side of the = is the OLD x, or xi-1; the one on the left side will be your "new" x, or xi.
Now, from there, you need to write the Java wrapper that will let you make that a method, which means writing a class.

Sounds like homework... so I won't give you a solution in code.
Anyways you need a linear congruential generator.
HINT: You need to write that mathematical formula as a function.
Steps:
Make a class.
Add the required state as member to the class.
Make a function within the class. Have it take input as necessary.
Write the formula for the congruential generator in Java (look up math operations in Java).
Return the result.
My Java is rusty, so I can't say I'm sure about this but these are probably errors:
int a = 25173, b = 13849, m = 32768;
double X_[i];//You need to define a constant array or use perhaps a list, you can't use i without defining it
for (int i = 1; i<100; i++)
X_[i] = (a*(X_[i]-1) + b) % m;
double X_[0] = 0.5;
double double = new double(); //You can't name a variable double, also types like double, don't need to be newed (I think)
System.out.println [new double]; //println uses () not [], in Java I think all functions need to use (), its not implied

EDIT:
Bongers:
[ ] are special symbols, if you intended for your variable to be named "X_[ i ]" that won't work. If you intended to make an array, you're making it too complicated.
You need to figure out if theY original equation was Xi - 1 or X(i-1) as that makes a huge difference in your programming. Xi - 1 is just one less than Xi. X(i-1) is the previous random number.
try doing some beginner java tutorials online. Here's a good place to start. Really try to understand the tutorials before continuing on to your problem.
Think about your problem this way.[Assuming the equation is X(i-1)] To generate the 3rd random number, X3, you will need to generate X2, which needs X1, which needs X0. But you have X0. So for any Xi, start with X0, generate X1, then generate X2, etc.. up until Xi.
You'll probably don't need to look into recursion like I first suggested.

A linear congruential generator is basically an expression which modifies a given value to produce the next value in the series. It takes the form:
xi+1 = (a.xi + b) mod m
as you've already specified (slightly differently: I was taught to always put xi+1 on the left and I still fear my math teachers 25 years later :-), where values for a, b and m are carefully chosen to give a decent range of values. Note that with the mod operator, you will always end up with a value between 0 and m-1 inclusive.
Note also that the values tend to be integral rather than floating point so if, as you request, you need a value in the range 0-0.999..., you'll need to divide the integral value by m to get that.
Having explained how it works, here's a simple Java program that implements it using values of a, b and m from your question:
public class myRnd {
// Linear congruential values for x(i+1) = (a * x(i) + b) % m.
final static int a = 25173;
final static int b = 13849;
final static int m = 32768;
// Current value for returning.
int x;
public myRnd() {
// Constructor simply sets value to half of m, equivalent to 0.5.
x = m / 2;
}
double next() {
// Calculate next value in sequence.
x = (a * x + b) % m;
// Return its 0-to-1 value.
return (double)x / m;
}
public static void main(String[] args) {
// Create a new myRnd instance.
myRnd r = new myRnd();
// Output 20 random numbers from it.
for (int i = 0; i < 20; i++) {
System.out.println (r.next());
}
}
}
And here's the output, which looks random to me anyway :-).
0.922637939453125
0.98748779296875
0.452850341796875
0.0242919921875
0.924957275390625
0.37213134765625
0.085052490234375
0.448974609375
0.460479736328125
0.07904052734375
0.109832763671875
0.2427978515625
0.372955322265625
0.82696533203125
0.620941162109375
0.37451171875
0.006134033203125
0.83465576171875
0.212127685546875
0.3128662109375

I would start by creating a class that holds a, b, m, the latest x (initialized to 0.5), and a method like getNextNumber().

public class generate_random_numbers {
public static void main(String[] args) {
int a = 25173, b = 13849, m = 32768;
Double[] X_ = new Double[100];
X_[0] = 0.5;
for (int i = 1; i < 100; i++) {
X_[i] = (a * X_[i - 1] + b) % m;
X_[i] = X_[i] / m;
System.out.println("X_[" + i + "] = " + X_[i]);
}
}
}

Related

Optimisation in Java Using Apache Commons Math

I'm trying to minimise a value in Java usingcommons-math. I've had a look at their documentation but I don't really get how to implement it.
Basically, in my code below, I have a Double which has the expected goals in a soccer match and I'd like to optimise the probability value of under 3 goals occurring in a game to 0.5.
import org.apache.commons.math3.distribution.PoissonDistribution;
public class Solver {
public static void main(String[] args) {
final Double expectedGoals = 2.9d;
final PoissonDistribution poissonGoals = new PoissonDistribution(expectedGoals);
Double probabilityUnderThreeGoals = 0d;
for (int score = 0; score < 15; score++) {
final Double probability =
poissonGoals.probability(score);
if (score < 3) {
probabilityUnderThreeGoals = probabilityUnderThreeGoals + probability;
}
}
System.out.println(probabilityUnderThreeGoals); //prints 0.44596319855718064, I want to optimise this to 0.5
}
}
The cumulative probability (<= x) of a Poisson random variable can be calculated by:
In your case, x is 2 and you want to find lambda (the mean) such that this is 0.5. You can type this into WolframAlpha and have it solve it for you. So rather than an optimisation problem, this is just a root-finding problem (though one could argue that optimisation problems are just finding roots.)
You can also do this with Apache Commons Maths, with one of the root finders.
int maximumGoals = 2;
double expectedProbability = 0.5;
UnivariateFunction f = x -> {
double sum = 0;
for (int i = 0; i <= maximumGoals; i++) {
sum += Math.pow(x, i) / CombinatoricsUtils.factorialDouble(i);
}
return sum * Math.exp(-x) - expectedProbability;
};
// the four parameters that "solve" takes are:
// the number of iterations, the function to solve, min and max of the root
// I've put some somewhat sensible values as an example. Feel free to change them
double answer = new BisectionSolver().solve(Integer.MAX_VALUE, f, 0, maximumGoals / expectedProbability);
System.out.println("Solved: " + answer);
System.out.println("Cumulative Probability: " + new PoissonDistribution(answer).cumulativeProbability(maximumGoals));
This prints:
Solved: 2.674060344696045
Cumulative Probability: 0.4999999923623868

Java while loop variable jumps for initial value

For the following simple while loop, once in every 5 runs, I get a list of wrong values for x, as if the values jump suddenly:
package test;
public class test_old {
public static void main(String [] args) {
double r0 = 0.1;
double r = 10;
double k = 0.05;
double x = 0;
double Tt = 0;
double T = 0;
while (Tt<=30) {
double xi = Math.random();
T = Math.log(1/xi)/(k*x + r0 + r);
Tt = Tt + T;
x = x + 1;
System.out.println(x);
}
}
}
Instead of getting 1.0, 2.0, 3.0, .. etc (usually around 4 values until Tt is bigger than 30), I sometimes get a list of x values that seems to go on for ever starting at for example 89462.0, or 19945.0. The list of x values is correctly incremented by 1, but it never stops.
I am a beginner using Eclipse.
Thank you everyone for your time!
Math.random () give values 0.0<=v<1.0
so if random gives you something like
v=0.99999999, log(1/v)=0.00000000001...
continue the calculation Tt=0+0.00000000001 will take like forever to be >30
just to test replace
double xi = Math.random();
by
double xi = 0.999999999999;
and run again
I don't know why this happen but it seems that the random gives you values like 0.9999...
so to avoid this you have to insure that random gives you smaller value
you can use this post
Math.random() explained

Checking whether a number is in Fibonacci Sequence?

It was asked to find a way to check whether a number is in the Fibonacci Sequence or not.
The constraints are
1≤T≤10^5
1≤N≤10^10
where the T is the number of test cases,
and N is the given number, the Fibonacci candidate to be tested.
I wrote it the following using the fact a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square :-
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 0 ; i < n; i++){
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest =(5 * (cand *cand)) + 4;
int bTest = (5 * (cand *cand)) - 4;
int sqrt1 = (int)Math.sqrt(aTest);// Taking square root of aTest, taking into account only the integer part.
int sqrt2 = (int)Math.sqrt(bTest);// Taking square root of bTest, taking into account only the integer part.
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
But its not clearing all the test cases? What bug fixes I can do ?
A much simpler solution is based on the fact that there are only 49 Fibonacci numbers below 10^10.
Precompute them and store them in an array or hash table for existency checks.
The runtime complexity will be O(log N + T):
Set<Long> nums = new HashSet<>();
long a = 1, b = 2;
while (a <= 10000000000L) {
nums.add(a);
long c = a + b;
a = b;
b = c;
}
// then for each query, use nums.contains() to check for Fibonacci-ness
If you want to go down the perfect square route, you might want to use arbitrary-precision arithmetics:
// find ceil(sqrt(n)) in O(log n) steps
BigInteger ceilSqrt(BigInteger n) {
// use binary search to find smallest x with x^2 >= n
BigInteger lo = BigInteger.valueOf(1),
hi = BigInteger.valueOf(n);
while (lo.compareTo(hi) < 0) {
BigInteger mid = lo.add(hi).divide(2);
if (mid.multiply(mid).compareTo(x) >= 0)
hi = mid;
else
lo = mid.add(BigInteger.ONE);
}
return lo;
}
// checks if n is a perfect square
boolean isPerfectSquare(BigInteger n) {
BigInteger x = ceilSqrt(n);
return x.multiply(x).equals(n);
}
Your tests for perfect squares involve floating point calculations. That is liable to give you incorrect answers because floating point calculations typically give you inaccurate results. (Floating point is at best an approximate to Real numbers.)
In this case sqrt(n*n) might give you n - epsilon for some small epsilon and (int) sqrt(n*n) would then be n - 1 instead of the expected n.
Restructure your code so that the tests are performed using integer arithmetic. But note that N < 1010 means that N2 < 1020. That is bigger than a long ... so you will need to use ...
UPDATE
There is more to it than this. First, Math.sqrt(double) is guaranteed to give you a double result that is rounded to the closest double value to the true square root. So you might think we are in the clear (as it were).
But the problem is that N multiplied by N has up to 20 significant digits ... which is more than can be represented when you widen the number to a double in order to make the sqrt call. (A double has 15.95 decimal digits of precision, according to Wikipedia.)
On top of that, the code as written does this:
int cand = sc.nextInt();
int aTest = (5 * (cand * cand)) + 4;
For large values of cand, that is liable to overflow. And it will even overflow if you use long instead of int ... given that the cand values may be up to 10^10. (A long can represent numbers up to +9,223,372,036,854,775,807 ... which is less than 1020.) And then we have to multiply N2 by 5.
In summary, while the code should work for small candidates, for really large ones it could either break when you attempt to read the candidate (as an int) or it could give the wrong answer due to integer overflow (as a long).
Fixing this requires a significant rethink. (Or deeper analysis than I have done to show that the computational hazards don't result in an incorrect answer for any large N in the range of possible inputs.)
According to this link a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square so you can basically do this check.
Hope this helps :)
Use binary search and the Fibonacci Q-matrix for a O((log n)^2) solution per test case if you use exponentiation by squaring.
Your solution does not work because it involves rounding floating point square roots of large numbers (potentially large enough not to even fit in a long), which sometimes will not be exact.
The binary search will work like this: find Q^m: if the m-th Fibonacci number is larger than yours, set right = m, if it is equal return true, else set left = m + 1.
As it was correctly said, sqrt could be rounded down. So:
Even if you use long instead of int, it has 18 digits.
even if you use Math.round(), not simply (int) or (long). Notice, your function wouldn't work correctly even on small numbers because of that.
double have 14 digits, long has 18, so you can't work with squares, you need 20 digits.
BigInteger and BigDecimal have no sqrt() function.
So, you have three ways:
write your own sqrt for BigInteger.
check all numbers around the found unprecise double sqrt() for being a real sqrt. That means also working with numbers and their errors simultaneously. (it's horror!)
count all Fibonacci numbers under 10^10 and compare against them.
The last variant is by far the simplest one.
Looks like to me the for-loop doesn't make any sense ?
When you remove the for-loop for me the program works as advertised:
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest = 5 * cand *cand + 4;
int bTest = 5 * cand *cand - 4;
int sqrt1 = (int)Math.sqrt(aTest);
int sqrt2 = (int)Math.sqrt(bTest);
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
You only need to test for a given candidate, yes? What is the for loop accomplishing? Could the results of the loop be throwing your testing program off?
Also, there is a missing } in the code. It will not run as posted without adding another } at the end, after which it runs fine for the following input:
10 1 2 3 4 5 6 7 8 9 10
IsFibo
IsFibo
IsFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
Taking into account all the above suggestions I wrote the following which passed all test cases
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long[] fib = new long[52];
Set<Long> fibSet = new HashSet<>(52);
fib[0] = 0L;
fib[1] = 1L;
for(int i = 2; i < 52; i++){
fib[i] = fib[i-1] + fib[i - 2];
fibSet.add(fib[i]);
}
int n = sc.nextInt();
long cand;
for(int i = 0; i < n; i++){
cand = sc.nextLong();
if(cand < 0){System.out.println("IsNotFibo");continue;}
if(fibSet.contains(cand)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
I wanted to be on the safer side hence I choose 52 as the number of elements in the Fibonacci sequence under consideration.

Interview: Find the whole cubes between range of two Integers

I just gave a coding interview on codility
I was asked the to implement the following, but i was not able to finish it in 20 minutes, now I am here to get ideas form this community
Write a function public int whole_cubes_count ( int A,int B ) where it should return whole cubes within the range
For example if A=8 and B=65, all the possible cubes in the range are 2^3 =8 , 3^3 =27 and 4^3=64, so the function should return count 3
I was not able to figure out how to identify a number as whole cube. How do I solve this problem?
A and B can have range from [-20000 to 20000]
This is what I tried
import java.util.Scanner;
class Solution1 {
public int whole_cubes_count ( int A,int B ) {
int count =0;
while(A<=B)
{
double v = Math.pow(A, 1 / 3); // << What goes here?
System.out.println(v);
if (v<=B)
{
count=count+1;
}
A =A +1;
}
return count ;
}
public static void main(String[] args)
{
System.out.println("Enter 1st Number");
Scanner scan = new Scanner(System.in);
int s1 = scan.nextInt();
System.out.println("Enter 2nd Number");
//Scanner scan = new Scanner(System.in);
int s2 = scan.nextInt();
Solution1 n = new Solution1();
System.out.println(n.whole_cubes_count (s1,s2));
}
}
Down and dirty, that's what I say.
If you only have 20 minutes, then they shouldn't expect super-optimized code. So don't even try. Play to the constraints of the system which say only +20,000 to -20,000 as the range. You know the cube values have to be within 27, since 27 * 27 * 27 = 19683.
public int whole_cubes_count(int a, int b) {
int count = 0;
int cube;
for (int x = -27; x <= 27; x++) {
cube = x * x * x;
if ((cube >= a) && (cube <= b))
count++;
}
return count;
}
For the positive cubes:
i = 1
while i^3 < max
++i
Similarly for the negative cubes but with an absolute value in the comparison.
To make this more general, you need to find the value of i where i^3 >= min, in the case that both min and max are positive. A similar solution works if both min and max are negative.
Well, it can be computed with O(1) complexity, we will need to find the largest cube that fits into the range, and the smallest one. All those that are between will obviously also be inside.
def n_cubes(A, B):
a_cr = int(math.ceil(cube_root(A)))
b_cr = int(math.floor(cube_root(B)))
if b_cr >= a_cr:
return b_cr - a_cr + 1
return 0
just make sure your cube_root returns integers for actual cubes. Complete solution as gist https://gist.github.com/tymofij/9035744
int countNoOfCubes(int a, int b) {
int count = 0;
for (int startsCube = (int) Math.ceil(Math.cbrt(a)); Math.pow(
startsCube, 3.0) <= b; startsCube++) {
count++;
}
return count;
}
The solution suggested by #Tim is faster than the one provided by #Erick, especially when A...B range increased.
Let me quote the ground from github here:
"one can notice that x³ > y³ for any x > y. (that is called monotonic function)
therefore for any x that lies in ∛A ≤ x ≤ ∛B, cube would fit: A ≤ x³ ≤ B
So to get number of cubes which lie within A..B, you can simply count number of integers between ∛A and ∛B. And number of integers between two numbers is their difference."
It seems perfectly correct, isn't it? It works for any power, not only for cube.
Here is my port of cube_root method for java:
/*
* make sure your cube_root returns integers for actual cubes
*/
static double cubeRoot(int x) {
//negative number cannot be raised to a fractional power
double res = Math.copySign(Math.pow(Math.abs(x), (1.0d/3)) , x);
long rounded_res = symmetricRound(res);
if (rounded_res * rounded_res * rounded_res == x)
return rounded_res;
else
return res;
}
private static long symmetricRound( double d ) {
return d < 0 ? - Math.round( -d ) : Math.round( d );
}
I am aware of Math.cbrt in java but with Math.pow approach it is easy to generalize the solution for other exponents.

Generate random numbers in increments

I need to generate n random numbers between a and b, but any two numbers cannot have a difference of less than c. All variables except n are floats (n is an int).
Solutions are preferred in java, but C/C++ is okay too.
Here is what code I have so far.:
static float getRandomNumberInRange(float min, float max) {
return (float) (min + (Math.random() * (max - min)));
}
static float[] randomNums(float a, float b, float c, int n) {
float minDistance = c;
float maxDistance = (b - a) - (n - 1) * c;
float[] randomNumArray = new float[n];
float random = getRandomNumberInRange(minDistance, maxDistance);
randomNumArray[0] = a + random;
for (int x = 1; x < n; x++) {
maxDistance = (b - a) - (randomNumArray[x - 1]) - (n - x - 1) * c;
random = getRandomNumberInRange(minDistance, maxDistance);
randomNumArray[x] = randomNumArray[x - 1] + random;
}
return randomNumArray;
}
If I run the function as such (10 times), I get the following output:
Input: randomNums(-1f, 1f, 0.1f, 10)
[-0.88, 0.85, 1.23, 1.3784, 1.49, 1.59, 1.69, 1.79, 1.89, 1.99]
[-0.73, -0.40, 0.17, 0.98, 1.47, 1.58, 1.69, 1.79, 1.89, 1.99]
[-0.49, 0.29, 0.54, 0.77, 1.09, 1.56, 1.69, 1.79, 1.89, 1.99]
I think a reasonable approach can be the following:
Total "space" is (b - a)
Remove the minimum required space (n-1)*c to obtain the remaining space
Shot (n-1) random numbers between 0 and 1 and scale them so that the sum is this just computed "optional space". Each of them will be a "slice" of space to be used.
First number is a
For each other number add c and the next "slice" to the previous number. Last number will be b.
If you don't want first and last to match a and b exactly then just create n+1 slices instead of n-1 and start with a+slice[0] instead of a.
The main idea is that once you remove the required spacing between the points (totalling (n-1)*c) the problem is just to find n-1 values so that the sum is the prescribed "optional space". To do this with a uniform distribution just shoot n-1 numbers, compute the sum and uniformly scale those numbers so that the sum is instead what you want by multiplying each of them by the constant factor k = wanted_sum / current_sum.
To obtain the final result you just use as spacing between a value and the previous one the sum of the mandatory part c and one of the randomly sampled variable parts.
An example in Python of the code needed for the computation is the following
space = b - a
slack = space - (n - 1)*c
slice = [random.random() for i in xrange(n-1)] # Pick (n-1) random numbers 0..1
k = slack / sum(slice) # Compute needed scaling
slice = [x*k for x in slice] # Scale to get slice sizes
result = [a]
for i in xrange(n-1):
result.append(result[-1] + slice[i] + c)
If you have random number X and you want another random number Y which is a minimum of A from X and a maximum of B from X, why not write that in your code?
float nextRandom(float base, float minDist, float maxDist) {
return base + minDist + (((float)Math.random()) * (maxDist - minDist));
}
by trying to keep the base out of the next number routine, you add a lot of complexity to your algorithm.
Though this does not exactly do what you need and does not incorporate the techinque being described in this thread, I believe that this code will prove to be useful as it will do what it seems like you want.
static float getRandomNumberInRange(float min, float max)
{
return (float) (min + (Math.random() * ((max - min))));
}
static float[] randomNums(float a, float b, float c, int n)
{
float averageDifference=(b-a)/n;
float[] randomNumArray = new float[n];
int random;
randomNumArray[0]=a+averageDifference/2;
for (int x = 1; x < n; x++)
randomNumArray[x]=randomNumArray[x-1]+averageDifference;
for (int x = 0; x < n; x++)
{
random = getRandomNumberInRange(-averageDifference/2, averageDifference/2);
randomNumArray[x]+=random;
}
return randomNumArray;
}
I need to generate n random numbers between a and b, but any two numbers cannot have a difference of less than c. All variables except n are floats (n is an int).
Solutions are preferred in java, but C/C++ is okay too.
First, what distribution? I'm going to assume a uniform distribution, but with that caveat that "any two numbers cannot have a difference of less than c". What you want is called "rejection sampling". There's a wikipedia article on the subject, plus a whole lot of other references on the 'net and in books (e.g. http://www.columbia.edu/~ks20/4703-Sigman/4703-07-Notes-ARM.pdf). Pseudocode, using some function random_uniform() that returns a random number drawn from U[0,1], and assuming a 1-based array (many languages use a 0-based array):
function generate_numbers (a, b, c, n, result)
result[1] = a + (b-a)*random_uniform()
for index from 2 to n
rejected = true
while (rejected)
result[index] = a + (b-a)*random_uniform()
rejected = abs (result[index] < result[index-1]) < c
end
end
Your solution was almost correct, here is the fix:
maxDistance = b - (randomNumArray[x - 1]) - (n - x - 1) * c;
I would do this by just generating n random numbers between a and b. Then I would sort them and get the first order differences, kicking out any numbers that generate a difference less than c, leaving me with m numbers. If m < n, I would just do it again, this time for n - m numbers, add those numbers to my original results, sort again, generate differences...and so on until I have n numbers.
Note, first order differences means x[1] - x[0], x[2] - x[1] and so on.
I don't have time to write this out in C but in R, it's pretty easy:
getRands<-function(n,a,b,c){
r<-c()
while(length(r) < n){
r<-sort(c(r,runif(n,a,b)))
r<-r[-(which(diff(r) <= c) + 1 )]
}
r
}
Note that if you are too aggresive with c relative to a and b, this kind of solution might take a long time to converge, or not converge at all if n * C > b -a
Also note, I don't mean for this R code to be a fully formed, production ready piece of code, just an illustration of the algorithm (for those who can follow R).
How about using a shifting range as you generate numbers to ensure that they don't appear too close?
static float[] randomNums(float min, float max, float separation, int n) {
float rangePerNumber = (max - min) / n;
// Check separation and range are consistent.
assert (rangePerNumber >= separation) : "You have a problem.";
float[] randomNumArray = new float[n];
// Set range for first random number
float lo = min;
float hi = lo + rangePerNumber;
for (int i = 0; i < n; ++i) {
float random = getRandomNumberInRange(lo, hi);
// Shift range for next random number.
lo = random + separation;
hi = lo + rangePerNumber;
randomNumArray[i] = random;
}
return randomNumArray;
}
I know you already accepted an answer, but I like this problem. I hope it's unique, I haven't gone through everyone's answers in detail just yet, and I need to run, so I'll just post this and hope it helps.
Think of it this way: Once you pick your first number, you have a chunk +/- c that you can no longer pick in.
So your first number is
range1=b-a
x=Random()*range1+a
At this point, x is somewhere between a and b (assuming Random() returns in 0 to 1). Now, we mark out the space we can no longer pick in
excludedMin=x-c
excludedMax=x+c
If x is close to either end, then it's easy, we just pick in the remaining space
if (excludedMin<=a)
{
range2=b-excludedMax
y=Random()*range2+excludedMax
}
Here, x is so close to a, that you won't get y between a and x, so you just pick between x+c and b. Likewise:
else if (excludedMax>=b)
{
range2=excludedMin-a
y=Random()*range2+a
}
Now if x is somewhere in the middle, we have to do a little magic
else
{
range2=b-a-2*c
y=Random()*range2+a
if (y>excludedMin) y+=2*c
}
What's going on here? Well, we know that the range y can lie in, is 2*c smaller than the whole space, so we pick a number somewhere in that smaller space. Now, if y is less than excludedMin, we know y "is to the left" of x-c, and we're all ok. However, if y>excluded min, we add 2*c (the total excluded space) to it, to ensure that it's greater than x+c, but it'll still be less than b because our range was reduced.
Now, it's easy to expand so n numbers, each time you just reduce the range by the excluded space among any of the other points. You continue until the excluded space equals the original range (b-a).
I know it's bad form to do a second answer, but I just thought of one...use a recursive search of the space:
Assume a global list of points: points
FillRandom(a,b,c)
{
range=b-a;
if (range>0)
{
x=Random()*range+a
points.Append(x)
FillRandom(a,x-c,c)
FillRandom(x+c,b,c)
}
}
I'll let you follow the recursion, but at the end, you'll have a list in points that fills the space with density 1/c

Categories