Computing an approximate value of Pi via Monte Carlo method in Java with streams
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I have this short program that attempts to compute an approximate value of $pi$:
package net.coderodde.fun;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* This class computes an approximate value of Pi.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Feb 23, 2018)
*/
public class MonteCarloPiComputer
/**
* The default radius of the simulated circle.
*/
private static final double DEFAULT_RADIUS = 0.5;
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random =
Objects.requireNonNull(
random,
"The input random number generator is null.");
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points, computes the percentage of all
* points within the radius from the center of the simulated square and
* multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @param radius the radius of the simulated circle.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples, double radius)
Point2D.Double center = new Point2D.Double(radius, radius);
double squareSideLength = 2.0 * radius;
long numberOfPointsWithinCircle =
IntStream.range(0, samples)
.mapToObj(
(i) ->
return new Point2D.Double(
squareSideLength * random.nextDouble(),
squareSideLength * random.nextDouble());
)
.filter((point) ->
return point.distance(center) < radius;
).count();
return (4.0 * numberOfPointsWithinCircle) / samples;
/**
* Computes an approximate value of Pi via a Monte Carlo method with default
* radius.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples)
return computeApproximateValueOfPi(samples, DEFAULT_RADIUS);
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation =
computer.computeApproximateValueOfPi(samples);
double percentage = approximation / Math.PI;
System.out.print(String.format("%7d: ", samples));
System.out.print(String.format("%10f", approximation));
System.out.println(
String.format(
", percentage from exact Pi: %10f",
(100.0 * percentage)));
Critique request
I would like to hear any comments and improvement suggestions.
java numerical-methods
add a comment |Â
up vote
4
down vote
favorite
I have this short program that attempts to compute an approximate value of $pi$:
package net.coderodde.fun;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* This class computes an approximate value of Pi.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Feb 23, 2018)
*/
public class MonteCarloPiComputer
/**
* The default radius of the simulated circle.
*/
private static final double DEFAULT_RADIUS = 0.5;
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random =
Objects.requireNonNull(
random,
"The input random number generator is null.");
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points, computes the percentage of all
* points within the radius from the center of the simulated square and
* multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @param radius the radius of the simulated circle.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples, double radius)
Point2D.Double center = new Point2D.Double(radius, radius);
double squareSideLength = 2.0 * radius;
long numberOfPointsWithinCircle =
IntStream.range(0, samples)
.mapToObj(
(i) ->
return new Point2D.Double(
squareSideLength * random.nextDouble(),
squareSideLength * random.nextDouble());
)
.filter((point) ->
return point.distance(center) < radius;
).count();
return (4.0 * numberOfPointsWithinCircle) / samples;
/**
* Computes an approximate value of Pi via a Monte Carlo method with default
* radius.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples)
return computeApproximateValueOfPi(samples, DEFAULT_RADIUS);
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation =
computer.computeApproximateValueOfPi(samples);
double percentage = approximation / Math.PI;
System.out.print(String.format("%7d: ", samples));
System.out.print(String.format("%10f", approximation));
System.out.println(
String.format(
", percentage from exact Pi: %10f",
(100.0 * percentage)));
Critique request
I would like to hear any comments and improvement suggestions.
java numerical-methods
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I have this short program that attempts to compute an approximate value of $pi$:
package net.coderodde.fun;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* This class computes an approximate value of Pi.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Feb 23, 2018)
*/
public class MonteCarloPiComputer
/**
* The default radius of the simulated circle.
*/
private static final double DEFAULT_RADIUS = 0.5;
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random =
Objects.requireNonNull(
random,
"The input random number generator is null.");
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points, computes the percentage of all
* points within the radius from the center of the simulated square and
* multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @param radius the radius of the simulated circle.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples, double radius)
Point2D.Double center = new Point2D.Double(radius, radius);
double squareSideLength = 2.0 * radius;
long numberOfPointsWithinCircle =
IntStream.range(0, samples)
.mapToObj(
(i) ->
return new Point2D.Double(
squareSideLength * random.nextDouble(),
squareSideLength * random.nextDouble());
)
.filter((point) ->
return point.distance(center) < radius;
).count();
return (4.0 * numberOfPointsWithinCircle) / samples;
/**
* Computes an approximate value of Pi via a Monte Carlo method with default
* radius.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples)
return computeApproximateValueOfPi(samples, DEFAULT_RADIUS);
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation =
computer.computeApproximateValueOfPi(samples);
double percentage = approximation / Math.PI;
System.out.print(String.format("%7d: ", samples));
System.out.print(String.format("%10f", approximation));
System.out.println(
String.format(
", percentage from exact Pi: %10f",
(100.0 * percentage)));
Critique request
I would like to hear any comments and improvement suggestions.
java numerical-methods
I have this short program that attempts to compute an approximate value of $pi$:
package net.coderodde.fun;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* This class computes an approximate value of Pi.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Feb 23, 2018)
*/
public class MonteCarloPiComputer
/**
* The default radius of the simulated circle.
*/
private static final double DEFAULT_RADIUS = 0.5;
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random =
Objects.requireNonNull(
random,
"The input random number generator is null.");
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points, computes the percentage of all
* points within the radius from the center of the simulated square and
* multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @param radius the radius of the simulated circle.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples, double radius)
Point2D.Double center = new Point2D.Double(radius, radius);
double squareSideLength = 2.0 * radius;
long numberOfPointsWithinCircle =
IntStream.range(0, samples)
.mapToObj(
(i) ->
return new Point2D.Double(
squareSideLength * random.nextDouble(),
squareSideLength * random.nextDouble());
)
.filter((point) ->
return point.distance(center) < radius;
).count();
return (4.0 * numberOfPointsWithinCircle) / samples;
/**
* Computes an approximate value of Pi via a Monte Carlo method with default
* radius.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double computeApproximateValueOfPi(int samples)
return computeApproximateValueOfPi(samples, DEFAULT_RADIUS);
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation =
computer.computeApproximateValueOfPi(samples);
double percentage = approximation / Math.PI;
System.out.print(String.format("%7d: ", samples));
System.out.print(String.format("%10f", approximation));
System.out.println(
String.format(
", percentage from exact Pi: %10f",
(100.0 * percentage)));
Critique request
I would like to hear any comments and improvement suggestions.
java numerical-methods
edited Feb 23 at 20:12
asked Feb 23 at 19:56
coderodde
15.5k533114
15.5k533114
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
You have some superfluous import
s. I also think that you can rename computeApproximateValueOfPi()
to approximatePi()
without losing any clarity.
The simulation is complicated by the fact that the circle is centered at an adjustable point (radius,ÃÂ radius)
. You could just as easily use a unit circle centered at the origin, and generate points in a square with x in the range [0,ÃÂ 1) and y in the range [0,ÃÂ 1). The computation is mathematically equivalent, with less shifting and scaling.
Furthermore, there is no need to instantiate a Point2D
for each generated point. You can use .distance(x, y)
. Better yet, avoid computing the square root by using .distanceSq(x, y)
.
The output routine in main()
could be improved. Your percentage
variable doesn't actually store a percentage as its name suggests; the 100ÃÂ happens in the formatting instead. Splitting up the formatting into several System.out.print()
calls defeats the purpose of String.format()
. I'd combine them all into one System.out.format()
call. Finally, the "percentage from" wording implies that you are calculating the difference; the calculation that you actually performed is what I would call "percentage of".
import java.awt.geom.Point2D;
import java.util.Objects;
import java.util.Random;
import java.util.stream.IntStream;
public class MonteCarloPiComputer
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random = Objects.requireNonNull(
random,
"The input random number generator is null."
);
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points in the upper-right quadrant,
* computes the fraction of all points within the radius from the origin
* and multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double approximatePi(int samples)
Random r = this.random;
Point2D.Double origin = new Point2D.Double();
long pointsWithinUnitArc = IntStream.range(0, samples)
.filter(i -> origin.distanceSq(r.nextDouble(), r.nextDouble()) < 1)
.count();
return (4.0 * pointsWithinUnitArc) / samples;
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation = computer.approximatePi(samples);
double pctDiff = 100 * (approximation - Math.PI) / Math.PI;
System.out.format("%7d: %10f, deviation from exact Pi: %+10f%%%n",
samples,
approximation,
pctDiff
);
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
You have some superfluous import
s. I also think that you can rename computeApproximateValueOfPi()
to approximatePi()
without losing any clarity.
The simulation is complicated by the fact that the circle is centered at an adjustable point (radius,ÃÂ radius)
. You could just as easily use a unit circle centered at the origin, and generate points in a square with x in the range [0,ÃÂ 1) and y in the range [0,ÃÂ 1). The computation is mathematically equivalent, with less shifting and scaling.
Furthermore, there is no need to instantiate a Point2D
for each generated point. You can use .distance(x, y)
. Better yet, avoid computing the square root by using .distanceSq(x, y)
.
The output routine in main()
could be improved. Your percentage
variable doesn't actually store a percentage as its name suggests; the 100ÃÂ happens in the formatting instead. Splitting up the formatting into several System.out.print()
calls defeats the purpose of String.format()
. I'd combine them all into one System.out.format()
call. Finally, the "percentage from" wording implies that you are calculating the difference; the calculation that you actually performed is what I would call "percentage of".
import java.awt.geom.Point2D;
import java.util.Objects;
import java.util.Random;
import java.util.stream.IntStream;
public class MonteCarloPiComputer
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random = Objects.requireNonNull(
random,
"The input random number generator is null."
);
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points in the upper-right quadrant,
* computes the fraction of all points within the radius from the origin
* and multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double approximatePi(int samples)
Random r = this.random;
Point2D.Double origin = new Point2D.Double();
long pointsWithinUnitArc = IntStream.range(0, samples)
.filter(i -> origin.distanceSq(r.nextDouble(), r.nextDouble()) < 1)
.count();
return (4.0 * pointsWithinUnitArc) / samples;
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation = computer.approximatePi(samples);
double pctDiff = 100 * (approximation - Math.PI) / Math.PI;
System.out.format("%7d: %10f, deviation from exact Pi: %+10f%%%n",
samples,
approximation,
pctDiff
);
add a comment |Â
up vote
2
down vote
accepted
You have some superfluous import
s. I also think that you can rename computeApproximateValueOfPi()
to approximatePi()
without losing any clarity.
The simulation is complicated by the fact that the circle is centered at an adjustable point (radius,ÃÂ radius)
. You could just as easily use a unit circle centered at the origin, and generate points in a square with x in the range [0,ÃÂ 1) and y in the range [0,ÃÂ 1). The computation is mathematically equivalent, with less shifting and scaling.
Furthermore, there is no need to instantiate a Point2D
for each generated point. You can use .distance(x, y)
. Better yet, avoid computing the square root by using .distanceSq(x, y)
.
The output routine in main()
could be improved. Your percentage
variable doesn't actually store a percentage as its name suggests; the 100ÃÂ happens in the formatting instead. Splitting up the formatting into several System.out.print()
calls defeats the purpose of String.format()
. I'd combine them all into one System.out.format()
call. Finally, the "percentage from" wording implies that you are calculating the difference; the calculation that you actually performed is what I would call "percentage of".
import java.awt.geom.Point2D;
import java.util.Objects;
import java.util.Random;
import java.util.stream.IntStream;
public class MonteCarloPiComputer
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random = Objects.requireNonNull(
random,
"The input random number generator is null."
);
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points in the upper-right quadrant,
* computes the fraction of all points within the radius from the origin
* and multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double approximatePi(int samples)
Random r = this.random;
Point2D.Double origin = new Point2D.Double();
long pointsWithinUnitArc = IntStream.range(0, samples)
.filter(i -> origin.distanceSq(r.nextDouble(), r.nextDouble()) < 1)
.count();
return (4.0 * pointsWithinUnitArc) / samples;
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation = computer.approximatePi(samples);
double pctDiff = 100 * (approximation - Math.PI) / Math.PI;
System.out.format("%7d: %10f, deviation from exact Pi: %+10f%%%n",
samples,
approximation,
pctDiff
);
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
You have some superfluous import
s. I also think that you can rename computeApproximateValueOfPi()
to approximatePi()
without losing any clarity.
The simulation is complicated by the fact that the circle is centered at an adjustable point (radius,ÃÂ radius)
. You could just as easily use a unit circle centered at the origin, and generate points in a square with x in the range [0,ÃÂ 1) and y in the range [0,ÃÂ 1). The computation is mathematically equivalent, with less shifting and scaling.
Furthermore, there is no need to instantiate a Point2D
for each generated point. You can use .distance(x, y)
. Better yet, avoid computing the square root by using .distanceSq(x, y)
.
The output routine in main()
could be improved. Your percentage
variable doesn't actually store a percentage as its name suggests; the 100ÃÂ happens in the formatting instead. Splitting up the formatting into several System.out.print()
calls defeats the purpose of String.format()
. I'd combine them all into one System.out.format()
call. Finally, the "percentage from" wording implies that you are calculating the difference; the calculation that you actually performed is what I would call "percentage of".
import java.awt.geom.Point2D;
import java.util.Objects;
import java.util.Random;
import java.util.stream.IntStream;
public class MonteCarloPiComputer
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random = Objects.requireNonNull(
random,
"The input random number generator is null."
);
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points in the upper-right quadrant,
* computes the fraction of all points within the radius from the origin
* and multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double approximatePi(int samples)
Random r = this.random;
Point2D.Double origin = new Point2D.Double();
long pointsWithinUnitArc = IntStream.range(0, samples)
.filter(i -> origin.distanceSq(r.nextDouble(), r.nextDouble()) < 1)
.count();
return (4.0 * pointsWithinUnitArc) / samples;
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation = computer.approximatePi(samples);
double pctDiff = 100 * (approximation - Math.PI) / Math.PI;
System.out.format("%7d: %10f, deviation from exact Pi: %+10f%%%n",
samples,
approximation,
pctDiff
);
You have some superfluous import
s. I also think that you can rename computeApproximateValueOfPi()
to approximatePi()
without losing any clarity.
The simulation is complicated by the fact that the circle is centered at an adjustable point (radius,ÃÂ radius)
. You could just as easily use a unit circle centered at the origin, and generate points in a square with x in the range [0,ÃÂ 1) and y in the range [0,ÃÂ 1). The computation is mathematically equivalent, with less shifting and scaling.
Furthermore, there is no need to instantiate a Point2D
for each generated point. You can use .distance(x, y)
. Better yet, avoid computing the square root by using .distanceSq(x, y)
.
The output routine in main()
could be improved. Your percentage
variable doesn't actually store a percentage as its name suggests; the 100ÃÂ happens in the formatting instead. Splitting up the formatting into several System.out.print()
calls defeats the purpose of String.format()
. I'd combine them all into one System.out.format()
call. Finally, the "percentage from" wording implies that you are calculating the difference; the calculation that you actually performed is what I would call "percentage of".
import java.awt.geom.Point2D;
import java.util.Objects;
import java.util.Random;
import java.util.stream.IntStream;
public class MonteCarloPiComputer
/**
* The random number generator.
*/
private final Random random;
public MonteCarloPiComputer(Random random)
this.random = Objects.requireNonNull(
random,
"The input random number generator is null."
);
public MonteCarloPiComputer()
this(new Random());
/**
* Computes an approximate value of Pi via a Monte Carlo method. The method
* creates @code samples random points in the upper-right quadrant,
* computes the fraction of all points within the radius from the origin
* and multiplies it by @code 4.0.
*
* @param samples the number of points to create.
* @return an approximate value of Pi.
*/
public double approximatePi(int samples)
Random r = this.random;
Point2D.Double origin = new Point2D.Double();
long pointsWithinUnitArc = IntStream.range(0, samples)
.filter(i -> origin.distanceSq(r.nextDouble(), r.nextDouble()) < 1)
.count();
return (4.0 * pointsWithinUnitArc) / samples;
public static void main(String args)
MonteCarloPiComputer computer = new MonteCarloPiComputer();
for (int samples = 100_000; samples <= 1_000_000; samples += 100_000)
double approximation = computer.approximatePi(samples);
double pctDiff = 100 * (approximation - Math.PI) / Math.PI;
System.out.format("%7d: %10f, deviation from exact Pi: %+10f%%%n",
samples,
approximation,
pctDiff
);
edited Feb 23 at 21:39
answered Feb 23 at 20:48
200_success
123k14142399
123k14142399
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188220%2fcomputing-an-approximate-value-of-pi-via-monte-carlo-method-in-java-with-streams%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password