There are many ways to find the pi rate, and recently a spark example uses the map and reduce methods to find the approximate value of pi. The idea of this algorithm is this:
Area of a circle with a radius of R CA =ΠXRXR
The area of the square of this garden sa = 4XRXR
π= CA/R/R = Cax4/sa
Based on the above deduction, we just know the circle and the square of the ratio of the area of the line. Then we randomly generate enough points in the area of the square, and we can get an approximate ratio by dividing the number of points in the circle by the total points. Of course the more the number of random values, the more accurate the results will be.
The implementation of the specific program, we assume that the Circle Center (1,1) of the radius of 1, so the square edges is 2. The map is then used to generate a random number and to determine whether the number is within a circle, and reduce to count the number within the circle. This algorithm uses SPARK to compute on the cluster, so we create multiple observable objects that work on different threads to simulate multiple tasks, and finally use the zip operator to collect the results of all tasks and average them. The code is as follows:
Private observable<double> createobservable (final int num) {
Return observable.range (0, num)
. Map (new Func1<integer, integer> () {
Public integer call (integer integer) {
Double x = mrandom.nextdouble () * 2-1;
Double y = mrandom.nextdouble () * 2-1;
Return (x * x + y * y) < 1? 1:0;
}
). Reduce (new Func2<integer, Integer, integer> () {
Public integer call (integer integer, integer integer2) {
int reduce = integer + Integer2;
return reduce;
}
})
. Map (new Func1<integer, double> () {
Public Double call (integer integer) {
Double v = 4.0 * integer/num;
System.out.println ("V:" + V);
return v;
}
})
. Subscribeon (Schedulers.computation ());
}
Public observable<double> getpi (int worknum, int num) {
arraylist<observable<double>> list = new arraylist<observable<double>> (workNum);
for (int i = 0; i < Worknum; i++) {
List.add (createobservable (num));
}
Use Zip to get the average value of all workers.
return Observable.zip (list, new funcn<double> () {
Public Double call (Object ... args) {
int len = args.length;
Double result = 0;
for (int i = 0; i < len; i++) {
result = = (Double) (Args[i]);
}
return Result/len;
}
});
}
Write testcase to test our program:
@Test
public void Test1 () {
final countdownlatch latch = new Countdownlatch (1);
&nb sp; pi pi = new Pi ();
final double[] result = {0};
PI.GETPI (4, 1000000)
Subscribe (new action1<double> () {
public void Call (Double adouble) {
System.out.print (adouble);
result[0] = adouble;
Latch.countdown ();
}
});
try {
Latch.await ();
catch (Interruptedexception e) {
E.printstacktrace ();
}
Assertequals (Pivalue, result[0], 0.001);
The results of the final run are as follows, the more points you create, the more results you get, and the more time you will spend calculating.
v:3.143012
v:3.138528
v:3.141844
v:3.144612
3.141999