Reputation: 11
I want to create 30 tables which consists of the following fields. For example,
Service_ID Service_Type consumer_feedback 75 Computing 1 35 Printer 0 33 Printer -1 3 rows in set (0.00 sec)
mysql> select * from consumer2; Service_ID Service_Type consumer_feedback 42 data 0 75 computing 0
mysql> select * from consumer3; Service_ID Service_Type consumer_feedback 43 data -1 41 data 1 72 computing -1
As you can infer from the above tables, I am getting the feedback values. I have generated these consumer_feedback
values, Service_ID
, Service_Type
using the concept of random numbers. I have used the function:
int min1=31;//printer
int max1=35;//the values are generated if the Service_Type is printer.
int provider1 = (int) (Math.random() * (max1 - min1 + 1) ) + min1;
int min2=41;//data
int max2 =45
int provider2 = (int) (Math.random() * (max2 - min2 + 1) ) + min2;
int min3=71;//computing
int max3=75;
int provider3 = (int) (Math.random() * (max3 - min3 + 1) ) + min3;
int min5 = -1;//feedback values
int max5 =1;
int feedback = (int) (Math.random() * (max5 - min5 + 1) ) + min5;
I need the Service_Types
to be distributed uniformly in all the 30 tables. Similarly I need feedback value of 1 to be generated many times other than 0 and -1.
Upvotes: 1
Views: 1180
Reputation: 124
You basically could have a list of consumer_feedback codes (equally distributed) and then you remove from it the codes but using a random index, that you can guarantee the exact number of each consumer_feedback code you want attributed to the 'Services'.
This is a Groovy code that exemplify the concept:
Assumptions:
To have an equal distribution I must assign a 'consumer_feedback code' to 33 'Services', and do it to each one. (For the sake of simplicity I choose numbers which are multiple of 3, as your question had 3 consumer_feedback codes)
//Creating the pool of available feedback codes
feedbacks = []
feedback = 0;
3.times {
33.times {
feedbacks << feedback
}
feedback++
}
rnd = new Random()
idx = 0
services = [:]
99.times {
services["Service_${idx++}"] =
feedbacks.remove(rnd.nextInt(feedbacks.size()))
}
println Collections.frequency(services.values(), 0)
println Collections.frequency(services.values(), 1)
println Collections.frequency(services.values(), 2)
println services
Upvotes: 0
Reputation: 2391
Edit: This answer is based on a misreading of the question, where I took "many times other than 0 and -1" to mean "many more times than 0 and -1". I'm leaving this answer up in case it's useful to someone else, but I doubt that it will be useful to the original poster.
To generate non-uniform random numbers, you will need to specify what the weights should be. For example, perhaps you want there to be three times as many 1's as there are 0's or -1's.
Here is a method that takes an array of three double
values, where the first value is the weight for -1, the second value is the weight for 0, and the third value is the weight for 1. This will generate -1, 0, or 1 with different probability based on the weights you give.
public int minusOneZeroOrOne(final double[] weights)
{
if (weights.length != 3)
throw new IllegalArgumentException("Must provide three weights");
double weightTotal = 0.0;
for (final double next : weights)
weightTotal += next;
double random = Math.random() * weightTotal;
if (random < weights[0])
return -1;
if (random < (weights[0] + weights[1]))
return 0;
return 1;
}
I tested this method by calling it with the weight array { 1.0, 1.0, 3.0 }
(that is, three times as many 1's as 0's or -1's) a hundred thousand times, and I got the following results:
$ java RandomTest | sort | uniq -c
20062 -1
19776 0
60162 1
As you can see, I got roughly three times as many "1" results as I got "0" results or "-1" results.
Upvotes: 0
Reputation: 10493
If you have 30 numbers and you need those 30 numbers to be found by your method, then a random generator won't be good for you. In that case, I think it would be more recommendable to add those 30 numbers to a List and call the method [Collections.shuffle][1] to shuffle the contents of the list, and then simply traverse it with a for ... each
block. If what you want are truly random numbers, then you should use the Random class, as Stephen explained.
Just remember that you should NOT create a new instance of the Random class every time you need a random number:
public Random() Creates a new random number generator. Its seed is initialized to a value based on the current time: public Random() { this(System.currentTimeMillis()); } Two Random objects created within the same millisecond will have the same sequence of random numbers.
From http://java.sun.com/j2se/1.4.2/docs/api/java/util/Random.html#Random()
It is a good practice to use the Random.nextInt(int n)
, providing the maximum integer value, as the common practice Random.nextInt() % n
doesn't generate evenly distributed numbers.
If you need a number between 50 and 100, it is simple as this:
Random r = new Random(); public int yourMethod() { return r.nextInt(50) + 50; }
[1]: http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html#shuffle(java.util.List, java.util.Random)
Upvotes: 2
Reputation: 719486
Under the hood, Math.random()
is using an instance of java.util.Random
to generate the numbers. You can avoid the messiness of mapping from doubles to integers by using Random's API directly:
Do something like this:
import java.util.Random;
...
private static Random prng = new Random();
...
int min1=31;//printer
int max1=35;//the values are generated if the Service_Type is printer.
int provider1 = prng.nextInt(max1 - min1 + 1) + min1;
Of course, the number's generated by Random are not very random, but they are certainly good enough for your use-case. However, I wonder if you wouldn't actually do better using a "round robin" strategy to distribute the load across the devices.
Upvotes: 1