Hi,
Ahmed, I may be doing something similar. I have simulation models driven by
probabilities (values between 0 and 1). In this range I used fixed decimal
precision probabilities by using BigDecimal. I have written code that does a
pseudo random test of a specific value in the range to return true or false. I
beleive this is without bias. For example for a test value of 0.75, 25% of the
time it is likely to return true. I've copied the test code for this below. It
is part of the generic package I have developed which I release via the
following URL:
http://www.geog.leeds.ac.uk/people/a.turner/src/andyt/java/generic/
(If you go to get the code, please get it from the subversion repository as the
bundled release is out of date.)
I have another method that returns a pseudo random BigDecimal at a given
decimal place precision within a specified range. This might also be useful to
you if you really need to have the value rather than perform a test.
A while ago I offered my code to math (because it does BigDecimal
exponentiation). I took some steps towards fullfilling the requirements for its
inclusion, but because of other demands on my time, I have not managed to
complete this which I am still keen to do this...
I hope this helps. Please let me know if it does. It may be that you are doing
something more complicated and this would need adapting to work with non
uniform distributions you are using.
Best wishes,
Andy
Here are the two methods I use for the random test, the private one is for
internal working:
/**
* Effectively this is the same as generating a random number between 0 and
* 1 and comparing it with probability and if it were higher then return
* false and otherwise return true
* @param a_Random
* @param probability 0 <= probability <=1
* @return true or false based on a random uniform test of probability
*/
public static boolean randomUniformTest(
Random a_Random,
BigDecimal probability,
int decimalPlaces,
RoundingMode a_RoundingMode) {
// Special case probability <= 0
if (probability.compareTo(BigDecimal.ZERO) != 1) {
if (probability.compareTo(BigDecimal.ZERO) == 0) {
return false;
} else {
System.out.println(
"Warning probabilty negative in "
+ Generic_BigDecimal.class
+ ".randomUniformTest(Random,BigDecimal). "
+ "Returning false.");
return false;
}
}
// Special case probability >= 1
if (probability.compareTo(BigDecimal.ONE) != -1) {
if (probability.compareTo(BigDecimal.ONE) == 0) {
return true;
} else {
System.out.println(
"Warning probabilty greater > 1 in "
+ Generic_BigDecimal.class
+ ".randomUniformTest(Random,BigDecimal). "
+ "Returning true.");
return true;
}
}
// Set decimalPlace precision to maximum of decimalPlaces and
// probability.scale();
int probabilityScale = probability.scale();
if (decimalPlaces < probabilityScale) {
System.out.println(
"Input decimalPlaces < probabilty.scale() in "
+ Generic_BigDecimal.class
+ ".randomUniformTest(Random,BigDecimal). "
+ "Set decimalPlaces = probabilty.scale().");
decimalPlaces = probabilityScale;
}
BigDecimal midTestValue = new BigDecimal("0.5");
BigDecimal half_BigDecimal = new BigDecimal("0.5");
BigDecimal two_BigDecimal = new BigDecimal("2.0");
if (probability.compareTo(midTestValue) == 0) {
return a_Random.nextBoolean();
}
if (probability.compareTo(midTestValue) == -1) {
return randomTest(
a_Random,
probability,
BigDecimal.ZERO,
BigDecimal.ONE,
midTestValue,
half_BigDecimal,
two_BigDecimal,
decimalPlaces,
a_RoundingMode);
} else {
return !randomTest(
a_Random,
BigDecimal.ONE.subtract(probability),
BigDecimal.ZERO,
BigDecimal.ONE,
midTestValue,
half_BigDecimal,
two_BigDecimal,
decimalPlaces,
a_RoundingMode);
}
}
private static boolean randomTest(
Random a_Random,
BigDecimal probability,
BigDecimal minTestValue,
BigDecimal maxTestValue,
BigDecimal midTestValue,
BigDecimal half_BigDecimal,
BigDecimal two_BigDecimal,
int decimalPlaces,
RoundingMode a_RoundingMode) {
if (probability.compareTo(midTestValue) == 0) {
return a_Random.nextBoolean();
}
boolean above = a_Random.nextBoolean();
if (above) {
if (probability.compareTo(midTestValue) == 1) {
// Test
BigDecimal newMinTestValue = midTestValue;
BigDecimal newMidTestValue = divide(
newMinTestValue.add(maxTestValue),
two_BigDecimal,
decimalPlaces,
a_RoundingMode);
return randomTest(
a_Random,
probability,
newMinTestValue,
maxTestValue,
newMidTestValue,
half_BigDecimal,
two_BigDecimal,
decimalPlaces,
a_RoundingMode);
} else {
return false;
}
} else {
if (probability.compareTo(midTestValue) == 1) {
return true;
} else {
//Test
BigDecimal newMaxTestValue = midTestValue;
BigDecimal newMidTestValue = divide(
newMaxTestValue.add(minTestValue),
two_BigDecimal,
decimalPlaces,
a_RoundingMode);
return randomTest(
a_Random,
probability,
minTestValue,
newMaxTestValue,
newMidTestValue,
half_BigDecimal,
two_BigDecimal,
decimalPlaces,
a_RoundingMode);
}
}
}
________________________________________
From: Ahmed Abdeen Hamed [[email protected]]
Sent: 23 October 2011 04:40
To: Commons Users List
Subject: Re: [math] Re: binomial random generator
Hi Phil,
Thanks very much for your quick response. I am doing some simulations that
produce probailities which are in turn must be compared to certains rates.
Here is an example of what I am doing:
if (randBinomial.nextBinomial(1, Simulation.MRATE)==1) {
// the condition can be replaced by the following uncommented condition
//randM.nextDouble() < Simulation.M_RATE;
if (gt[i] == 0) {
gt[i] = 1;
} else {
gt[i] = 0;
}
}
Please let me know if I am using Binomial object and its method correctly.
Thanks again!
Ahmed
On Sat, Oct 22, 2011 at 11:29 PM, Phil Steitz <[email protected]> wrote:
> On 10/22/11 8:15 PM, Ahmed Abdeen Hamed wrote:
> > Hello friends,
> >
> > I am using the following code in a program I am writing:
> > private static JDKRandomGenerator rg = new JDKRandomGenerator();
> > private static RandomDataImpl randBinomial = new RandomDataImpl(rg);
> >
> > However, it is slowing down things very much. When I replace generator
> with
> > a java.util.Random object it works fine without the performance issues.
> Is
> > that expected with this library? Is there any work around? My programs
> are
> > very time consuming and I have been repeatedly running them. I really
> need
> > some tips if there is anything I can do to enhance the performance.
>
> That depends on how you are using randBinomial above. Can you share
> the code that uses randBinomial and what you mean by "replace
> generator with a java.util.Random object?" It will also help to
> describe what exactly you are trying to accomplish with the code.
>
> Phil
> >
> > Thanks very much!
> > Ahmed
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]