This easy program program computes an estimate of pi by simulating dart throws onto a square.
Сonditions: Generate a random floating-point number and transform it so that it is between -1 and 1.
Store in x. Repeat for y. Check that (x, y) is in the unit circle, that is, the distance between (0, 0) and (x, y) is <= 1.
After this, need to find the ratio hits / tries is approximately the same as the ratio circle area / square area = pi / 4. (square is 1 per 1).
Code:
public class MonteCarlo {
public static void main(String[] args)
{
System.out.println("Number of tries");
Random generator = new Random(42);
Scanner in = new Scanner(System.in);
int tries = in.nextInt();
int hits = 0;
double x, y;
for (int i = 1; i <= tries; i++)
{
// Generate two random numbers between -1 and 1
int plusOrMinus = generator.nextInt(1000);
if (plusOrMinus > 500) x = generator.nextDouble();
else x = -generator.nextDouble();
plusOrMinus = generator.nextInt(10000);
if (plusOrMinus > 5000) y = generator.nextDouble();
else y = -generator.nextDouble();
if (Math.sqrt((x * x) + (y * y)) <= 1) // Check whether the point lies in the unit circle
{
hits++;
}
}
double piEstimate = 4.0 * hits / tries;
System.out.println("Estimate for pi: " + piEstimate);
}
}
Testing output:
Actual output Expected output
-----------------------------------------------
Number of tries Number of tries
1000 1000
- Estimate for pi: 3.176 Estimate for pi: 3.312
Actual output Expected output
-----------------------------------------------------
Number of tries Number of tries
1000000 1000000
- Estimate for pi: 3.141912 Estimate for pi: 3.143472
Maybe, does exist other approaches to find this solution?
Any suggestions.
For generating the random double between -1 and 1, try:
generator.nextDouble() * 2 - 1
BTW: If you keep initializing your random with a static seed, you'll always get the same result. Otherwise, if you are concerned that your result is not good enough, keep in mind that the Monte Carlo is only an approximation. After all, it's based on random numbers, so the result will vary from the sample solution ;-)
A generalized solution to turn a Uniform(0,1) into a Uniform(a,b) (where a < b) is
(b - a) * generator.nextDouble() + a
As #winSharp93 pointed out, you should expect variation but you can quantify the margin of error as a statistical confidence interval. If you calculate
halfWidth = 1.96 * Math.sqrt(piEstimate * (4.0 - piEstimate) / tries);
then the actual value of pi should fall between piEstimate - halfWidth and piEstimate + halfWidth 95% of the time. You can see from the halfWidth calculation that the range containing pi will shrink (but not linearly) as the number of tries is increased. You can adjust the confidence level from 95% to other values by replacing 1.96 with an alternative scale value out of a Standard Normal table.
Related
My task is to implement the cos(x) function withou using Math. library and with the taylor polynom, my code looks like this:
public class Cosinus {
public static void main(String[] args) {
/*if(args.length == 0){
System.out.println("ERROR: Geben Sie ein Argument für x ein!");
return;
}*/
double x = 5;
double summand1 = (x*x) / 2;
double summand2 = (x*x*x*x) / (2*3*4);
double summand3 = (x*x*x*x*x*x) / (2*3*4*5*6);
double summand4 = (x*x*x*x*x*x*x*x) / (2*3*4*5*6*7*8);
double summand5 = (x*x*x*x*x*x*x*x*x*x) / (2*3*4*5*6*7*8*9*10);
double summand6 = (x*x*x*x*x*x*x*x*x*x*x*x) / (2*3*4*5*6*7*8*9*10*11*12);
double summand7 = (x*x*x*x*x*x*x*x*x*x*x*x*x*x) / (2*3*4*5*6*7*8*9*10*11*12*13*14);
//double summand8 = (x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x) / (2*3*4*5*6*7*8*9*10*11*12*13*14*15*16);
//double summand9 = (x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x) / (2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18);
//double summand10 = (x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x) / (2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20);
double cosinusFunktion = (((((((1 - summand1) + summand2) - summand3) + summand4) - summand5) + summand6) - summand7);
System.out.println(cosinusFunktion);
}
}
For x = 1, 2, 3, and 4 Y is between 1 and -1
but with x = 5 it goes too -4 and if the x are even getting bigger this continues too 1287918274.
I cant solve this task but tthe task says it is enough to implement this funktion iwth the taylor polynom and the first 11 summand. I tried this too, but then even with x = 1 the bounds are broken. How can i solve this, so x = 42.5 is in bound of -1 and 1?
Tried more summands to make the result more excact, but the bounds get broken even more.
tried implement the periodicity of x-2*PI, but I dont know where to put it and results get messed up eeven more.
you are getting an integer overflow for the factorial in the summand7 line
as a simple fix you can change the line to:
double summand7 = (x*x*x*x*x*x*x*x*x*x*x*x*x*x) / ((double) 2*3*4*5*6*7*8*9*10*11*12*13*14);
The Taylor expansion will always blow up for larger inputs. However, since:
sin(x) = sin(x + n*2*pi) // for any integer n
You can simply pre-process you input with a modulus function to prevent your output from blowing up.
I can't test compile right now, but if memory serves, you would add one of the following lines prior to computing your first summand:
x = x%(Math.PI*2)
Or, if you can't use Math
x = x%((double)3.14159265358979323846*2)
Essentially i want to find an estimate of pi by throwing a dart at the unit circle. So I want to throw a dart a the positive x and y quadrant of the unit circle , each dart thrown will give me a random position in the x and y direction that is less that 1. I then need to find the distance from the origin from that point. The approximation of pi will come from when the distance of the dart from the origin is less than 1 when calculated, this will count as a hit, anything else will count as a miss. Using this number pi is found by (#hits/#of tosses)*4 since i will only be looking at 1/4 of the circle .I then want to print a table with different results depending on how many darts are thrown. my code is below, I'm confused on a lot of things, mainly how do I collect all the data and print it all, I was thinking of using an ArrayList of arrays of ints since it will not be limited to the amount of trials I want to do but I am unsure on how to proceed. Any help is useful, thanks!
public static void main(String[]args){
int[] darts_Thrown = {10, 100, 1000, 10000, 100000,1000000};
// for( int i = 0; i < points.length; i++){
// System.out.print(points[i]);
// }
for (int i = 0; i < darts_Thrown.length;i++){
for (int j = 0; j < darts_Thrown[i]; j++){
int test = 0;
double [] points = getPoint();
// distanceToOrigin(points[0],points[1]);
// getHits();
test++;
System.out.printf("%d",test);
}
System.out.printf("%n%s", "hi ");
}
}
public static double[] getPoint()//code to generate x and y and return them in a double array
{
double[] point_X_Y = {Math.random(),Math.random()};
return point_X_Y;
}
public static double distanceToOrigin(double x,double y) //code to compute distance from point (x,y) to origin (0,0)
{
double distance = Math.sqrt((Math.pow(x,2))+(Math.pow(y,2))); // used to find distance from origin
return distance;
}
public static int getHits(int n)
{
int hits = 0;
int misses=0;
//double distance = distanceToOrigin(points[0], points[1]);
//if (distance < 0){
// hits++;
// return hits;
// }
// else{
// misses++;
//return misses;
// }
// return 0;
//code to get hits given n= number of darts
}
}
The formula #hits/#tosses is correct in thought, but it's gotta be too small, since it can't possibly be larger than 1. It turns out that that formula will approximate the value of PI/4, so the approximation of PI is #hits/#tosses*4.
For each trial, it isn't really practical to "collect all the data and print it all", if you want to get a reasonable approximation of PI by the end, because it's going to take a million or so trials to get at all close. I found that 1M trials gives a pretty good result, and 10M often gives you the right result to 4 decimal places. There's no use in printing even a few 100 individual trials, much less 1M of them. So I think all you can really print is the trial number, the number of throws, the number of hits, and the final approximation of PI. Here's code that does that:
public class Test {
public static void main(String[]args){
int[] darts_Thrown = {10, 100, 1000, 10000, 100000, 1000000, 10000000};
for (int i = 0; i < darts_Thrown.length;i++){
int hits = 0;
for (int j = 0; j < darts_Thrown[i]; j++){
double [] points = getPoint();
double distance = distanceToOrigin(points[0],points[1]);
if (distance <= 1.0)
hits++;
}
double pi_est = (double)hits / darts_Thrown[i] * 4.0;
System.out.printf("Trial: %d Throws: %d Hits: %d Approximation of PI (hits/throws*4): %.4f\n",
i, darts_Thrown[i], hits, pi_est);
}
}
public static double[] getPoint()//code to generate x and y and return them in a double array
{
final double[] doubles = {Math.random(), Math.random()};
return doubles;
}
public static double distanceToOrigin(double x,double y) //code to compute distance from point (x,y) to origin (0,0)
{
double distance = Math.sqrt((Math.pow(x,2))+(Math.pow(y,2))); // used to find distance from origin
return distance;
}
}
Result:
Trial: 1 Throws: 10 Hits: 8 Approximation of PI (hits/throws*4): 3.2000
Trial: 2 Throws: 100 Hits: 79 Approximation of PI (hits/throws*4): 3.1600
Trial: 3 Throws: 1000 Hits: 773 Approximation of PI (hits/throws*4): 3.0920
Trial: 4 Throws: 10000 Hits: 7800 Approximation of PI (hits/throws*4): 3.1200
Trial: 5 Throws: 100000 Hits: 78409 Approximation of PI (hits/throws*4): 3.1364
Trial: 6 Throws: 1000000 Hits: 785250 Approximation of PI (hits/throws*4): 3.1410
Trial: 7 Throws: 10000000 Hits: 7852455 Approximation of PI (hits/throws*4): 3.1410
The formula is pretty easy to derive. For a circle with radius 1 centered at the origin, 1/4 of it will be in the quadrant x=0-1, y=0-1. The points inside that circle are 1 unit from the origin or closer, so those are all 'hits'. A 1/4 of a circle of radius 1 has an area of PI * r^2 / 4 = PI * 1^2 / 4 = PI/4. The entire target area is x * y = 1 * 1 = 1. So hits/throws = (PI/4)/(1) = PI/4. Multiply both sides by 4 to get PI = hits/throws * 4.
I am not very familiar with how to alter the range of both Math.random or a new Random() to generate a double like this. I need to be able to generate a double between -10 and 25 cents (my program is dealing with money; hence why I said cents). And a separate instance is generating a random double between 90 and -75 cents. I saw this when I was searching for my answer:
double result = Math.random() * (upper - lower) + lower;
But when I implemented the idea into my code, the range didn't seem to work when using a range between a positive and a negative number...
I tested it with the upper limit of 0.25 and lower of -0.10, but noticed it printed 0.3567587946356543 at one instance of the test I did. So by this I concluded that I obviously didn't adjust the range correctly..
Please help :(
This is my first time using stackoverflow so please go easy on me, I will elaborate if anything I said didn't make sense..
This is my existing method using this code:
public double variation(double price){
//formula: (Math.random() * range) + min; where range = max - min
//80% of the time returns amount between -10 & 25 cents
if(Math.random() > 0.19){
return (Math.random() * 0.35) - 0.10;
}
//20% of the time returns amount between -75 & 90 cents
return (Math.random() * 1.65) - 0.75;
}
I know the method takes in a double price that it doesn't use; it's part of the teacher's requirements to take in a double price but to disregard its value. So ignore that please.
Now you have included all your code in the question, so my answer is changed to:
When it printed 0.3567587946356543 then it comes from the 20% part with range -.75 to 0.90 when the first Math.random() call in if(Math.random() > 0.19){ becomes false.
Old answer:
I think you forgot the minus at the lower value:
double upper = 0.25;
double lower = -0.10;
double result = Math.random() * (upper - lower) + lower;
To generate between -10 and 25, try doing :-
Random r = new Random();
int d = r.nextInt(35)+1;
d = d - 10;
double result = d/100.0;
or a one liner
double result = ((r.nextInt(35)+1)-10)/100.0;
Looks like your formula is actually correct:
double result = Math.random() * (upper - lower) + lower;
You can test it by putting the min and max possible random (which is zero, 1)
Random Value | Result
---------------------------
0 | -0.1 (lower)
1 | 0.25
0.5 | 0.075
0.01 | -0.0965
Working back to get the Random value for the result to be 0.356758795, the Math.random() must return 1.305025128 which is not gonna be the case. :)
Having said that, Apache Commons3 has this nifty method RandomUtils.nextDouble(double startInclusive, double endInclusive); that does it for you.
To get an output with a long decimal:
it's a little bit rough, but it gets the job done.
Random rand = new Random();// creates 'Random' method
int number = rand.nextInt(35)+1;// gets a random integer out of 35
double randDouble = rand.nextDouble();//gets a random double
double finalNumber = ((number + randDouble)-10)/100;//adds the integer and the double,
//subtracts ten, and divides by 100
System.out.println(finalNumber);// prints the number
Here are some examples of the output (copied and pasted exactly).
0.22748959958842008
0.1963085030978741
0.17300671109908058
-0.002656673961685705
-0.08854411636457332
0.03578255664449403
To get an output with a two digit output:
Random rand = new Random(); // creates 'Random' method
float x = rand.nextInt(35)+1; // gets a random integer(0 through 35)
float y = x - 10; // subtracts that number by ten(making the new range -10 through 25)
float z = y/100; // puts number in decimal form
NOTICE this line int number = rand.nextInt(35)+1(in the long decimal version). The reason you have to do +1 at the end is because Java understands 1 as 0. see chart below
JAVA |0 1 2 3 4 5
-------|-----------
HUMANS |1 2 3 4 5 6
I took 400.0 and - 400.0 for example.
double min = 400.0;
double max = 2 * min;
System.out.println(Math.random() * max - min);
And the output is
138.0921773815627
212.7567891431654
9.063135840057157
-256.8594518458244
-99.84573995806142
116.53331370219462
33.29613621235126
I am trying to solve this task:
In this exercise you will write a program that estimates the value of π. Pretend that we are looking at a dartboard in the picture above. If the square is 2units wide and 2 units high, the radius of the circle within the square is 1 unit. Then the area of the circle is π*r2 = π*12 = π. The area of the square will be 2*2 = 4.
The estimation of π will work by randomly “throwing darts” at the dartboard. We will assume that every dart will hit the board but the location of that strike will be random so some darts will land inside the circle and some will land outside the circle. The calculation of π is then the ratio of the number of darts that land inside the circle to the total number of darts, multiplied by 4. Note that as we increase the number of darts used in the simulation, the accuracy improves.
Follow the steps to complete the program:
Declare variables that represent x, y coordinates of a dart, the distance of the dart from the origin, the number of darts that land inside the circle, and the total number of darts.
Read in the total number of darts (N) from the user and create an instance of the Random class.
Create a loop that runs N times. Inside the loop, you will use the nextFloat() method of the Random class to create x, y coordinates randomly, and then compute the distance of the dart from the origin. Determine whether the dart lands inside or outside of the circle.
Compute π using the estimation algorithm.
Run the program with increasing numbers from 100 to 100,000,000 and observe the accuracy of π.
Here is my program I wrote. It works to some extent, but results seems incorrect for input like 100000. Can anyone explain what's wrong with my code?
import java.util.Scanner;
import java.util.Random;
public class calculatePI {
public static void main(String[] args) {
double x;
double y;
double distance;
int i = 0;
float inside = 0;
float outside = 0;
float totalDarts;
Scanner scan = new Scanner(System.in);
Random random = new Random();
System.out.println("Enter the number of darts: ");
totalDarts = scan.nextFloat();
for (i = 1; i < totalDarts; i++) {
x = Math.abs(random.nextFloat() % 2);
y = Math.abs(random.nextFloat() % 2);
distance = (float) Math.sqrt(Math.pow(x - 1, 2)
+ Math.pow(y - 1, 2));
if (distance <= 1)
inside++;
else
outside++;
}
System.out.println("Total number of arrows inside circle:" + inside);
System.out.println("Estimated value of Pie: "
+ (((inside * 4) / (double) totalDarts)));
}
}
To solve your problem change types of
float inside = 0;
float outside = 0;
float totalDarts;
to either int or long.
Problem with float is that not all integers can be represented precisely by this type. float uses 24 bits to store number (rest of bits are used to store sign, and precision) which means that without loss of precision float can store int values only in range -16777216 to 16777216.
You can observe this with
System.out.println(16777216f);
System.out.println(16777217f);
System.out.println(16777218f);
which prints
1.6777216E7
1.6777216E7
1.6777218E7
Now you see that 16777217 can't be represented precisely and will be represented with 16777216. This means that 16777216f+1 will still return 16777216F, which blocks your totalDarts from being greater number than 16777216, which causes problem for bigger numbers.
I need help writing a program that uses binary search to recursively compute a square root (rounded down to the nearest integer) of an input non-negative integer.
This is what I have so far:
import java.util.Scanner;
public class Sqrt {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("Enter A Valid Integer: ");
int value = console.nextInt();
calculateSquareRoot(value);
}
public static int calculateSquareRoot(int value) {
while (value > 0) {
double sqrt = (int) Math.sqrt(value);
System.out.println(sqrt);
}
return -1;
}
}
The fact that it has to use binary search to compute the square root is the part that is confusing me. If anyone has any suggestions on how to do this, it would be greatly appreciated. Thank you
Teh codez:
def sqrt(n):
low = 0
high = n+1
while high-low > 1:
mid = (low+high) / 2
if mid*mid <= n:
low = mid
else:
high = mid
return low
To understand it, just think of the loop invariant, namely:
lowlow <= n < highhigh
If you understand this code, writing a recursive version should be trivial.
You can use this java method (Iterative)
public class Solution {
// basic idea is using binary search
public int sqrt(int x) {
if(x == 0 || x == 1) {
return x;
}
int start = 1, end = x / 2;
while(start <= end) {
int mid = start + (end - start) / 2;
if(mid == x / mid) {
return mid;
}
if(mid < x / mid) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return start - 1;
}
}
You can drive your own recursive method
Essentially the idea is that you can use binary search to get closer to the answer.
For example, say you are given 14 as an input. Then, you are sure that the square root of 14 is between 0 and 14. So, 0 and 14 are your current "boundaries". You bisect these two end points and obtain the mid point: 7. Then you try 7 as a candidate - If the square of 7 is greater than 14, then you have a new boundary (0,7); otherwise you would have a new boundary (7,14).
You keep repeating this bisection until you are "close enough" to the answer, for example you have a number square of which is within 14-0.01 and 14+0.01 - then you declare that as the answer.
OK, that much hint should be good enough for HW. Don't forget to cite StackOverflow.
I'm assuming this is homework so I'm only going to give a hint.
To conduct a binary search, you pick a point as close as possible the median of possible correct values. So the question becomes what is a typical median value for a square root, that is either constant or can be computed via multiplication. Obviously using an arbitrary constant will not work for most inputs, so you need to arrive at your guess by multiplying the input by a constant.
As for what that constant C to multiply by should be, that should be chosen based on what values you expect as input. For example, if you expect your inputs to be around 250,000, then:
C * 250,000 ~= sqrt(250,000)
C = sqrt(250,000) / 250,000
C = 500 / 250,000
C = 1 / 500
I see two important computing concepts in your question. The first is binary search, the second is recursion. Since this is homework, here is a contribution towards understanding a binary search, recursion and how to think about them.
Think of binary search as dividing the solution "space" in half, keeping the half the solution is in and doing that in succession so that the process converges on the solution. The key concepts for doing this are that you need to engineer a solution "space" that has the following properties:
1) can be subdivided, usually in half or at least two pieces
2) of the two pieces after subdivision, there is a way to determine which half has the solution so that the process can be repeated on only one half.
Recursion involves a function (method in O-O speak) invoking itself. Recursion works really well for a process that converges to a conclusion. It either recurses forever or until you run out of some resource, usually memory, and it fatally stops. The two key concepts for recursion are:
1) convergence through some invariance (more on invariance below).
2) termination condition (one that recognizes sufficient convergence).
Now, for your square root routine. The requirements for the routine are:
1) Integer input.
2) Integer square-root approximation that gives the floor integer closest to the actual square root.
3) Use recursion.
4) Use binary search.
It helps to know some mathematics about square roots for this. Elementary calculus and analytical geometry concepts are helpful too. Lets do some reasoning.
We have an arbitrary positive integer x. We want its root y. If we choose some test value for y, we can see if it is the root of x if y * y = x. If y is too big, y * y > x. if y is too small, y * y < x. We also know that 0 <= root <= x and that square-roots of 0 and 1 are trivially zero and 1. Since we are looking for largest integer where y * y <= x (i.e. a floor value) we'll have to account for that too.
Here is some mathematical reasoning to help. We know that x = y * y where y is the square root of x. That means: y = x/y.
Hmmm... what happens if y is to large to be the square root of x? Then: x < y * y and: x/y < y which means x/y is also too small to be the square root of x. So we know that, for y too large, x/y < square-root of x < y. So, lets find a new y, say y1, between x/y and y as a new test value. The average of x/y and y will do. y1 = (x/y0 + y0)/2 will give a y1 that is closer to the square root of x than y0 if y0 is too large.
Does this converge? Well, in mathematics using positive real numbers, the average will always be above the value but getting closer each iteration. This satisfies the condition that we successively divide the solution "space" into two parts and know which of the two to keep. In this case, we successively calculate new values below previous ones and below which the answer still lies, allowing us to discard all values above the new one. We stop when we reach a condition where no more new values above the answer exist. Using computers, however, results in binary approximations of real numbers. With integers, there is truncation in division. This may affect the convergence beneficially or adversely. In addition, your answer is supposed to be the largest integer smaller than or equal to the square root. It's wise to take a look at the kind of convergence we will get.
Because of integer division turncation, y1 = (x/y0 + y0)/2 will converge until successive iterations reach an integer root or a floor value for (i.e. the largest integer less than) the root. This is ideal. If we start with a proposed value for the root that has to be larger than the root, say x itself, the first value for yn where yn * yn <= x is the desired result.
The simple answer is that, when we start with y0 > y, the first new yn that is less than or equal to y, then y - yn < 1. That is, yn is now the floor value for which we've been looking and we now have a termination condition that exactly satisfies the conditions for the required answer.
Here are basic iterative and recursive solutions. The solutions don't incude safety features to ensure negative values are not input for x. The one major concern is to avoid dividing by zero in case someone wants to find the square root of 0. Since that is a trivial answer, both the recursive and iterative methods return 0 before division by zero can take place. Both the recursive and iterative solutions work with the trivial cases for finding the square roots of 0 and of 1.
There is another analysis that always has to be done with int and long arithmetic in Java. A major concern is integer overflow since Java does nothing about int or long overflow. Overflow results in twos-complement values (look that up elsewhere) that can lead to bogus results and Java does not throw exceptions with int or long overflow.
In this case, it is easy to avoid arithmetic that could result in an internal overflow with large values of x. If we create a termination condition such as y0 * y0 < x we risk overflow if x is greater than the square root of Integer.MAX_VALUE since y0 * y0, an intermediate value, will immediately exceed the maximum int value. However, we can rearrange the termination condition to y0 < x / y0. We still have a problem with the calculations: ((x / y0) + y0) / 2) if x and y0 are Integer.MAX_VALUE since it wll attempt Integer.MAX_VALUE + 1. However, we can always start with a value less than x that is guaranteed to be > y. x / 2 works for all values of x > 1. Since the square root of x where x is either 0 or 1 is simply x, we can easily test for those values and simply return the correct and trivial value. You can construct code to prevent using values < 0 or values > Integer.MAX_VALUE. The same can be applied if we use long instead of int. Welcome to computing in the real world!
public static int intSqRootRecursive (int x) {
// square roots of 0 and 1 are trivial and x / 2 for
// the y0 parameter will cause a divide-by-zero exception
if (x == 0 || x == 1) {
return x;
}
// starting with x / 2 avoids overflow issues
return intSqRootRecursive (x, x / 2);
} // end intSqRootRecursive
private static int intSqRootRecursive(int x, int y0) {
// square roots of 0 and 1 are trivial
// y0 == 0 will cause a divide-by-zero exception
if (x == 0 || x == 1) {
return x;
} // end if
if (y0 > x / y0) {
int y1 = ((x / y0) + y0) / 2;
return intSqRootRecursive(x, y1);
} else {
return y0;
} // end if...else
} // end intSqRootRecursive
public static int intSqRootIterative(int x) {
// square roots of 0 and 1 are trivial and
// y == 0 will cause a divide-by-zero exception
if (x == 0 || x == 1) {
return x;
} // end if
int y;
// starting with y = x / 2 avoids overflow issues
for (y = x / 2; y > x / y; y = ((x / y) + y) / 2);
return y;
} // end intSqRootIterative
You can test the recursive solution to find out how many instances will result on the frame stack, but you will see that it converges very fast. It's interesting to see that the iterative solution is much smaller and faster than the recursive one, something that is often not the case and is why recursion gets used where it can be predicted that stack resources are sufficient for the recursion depth.
Here is the recursive solution in Java using binary search :
public class FindSquareRoot {
public static void main(String[] args) {
int inputNumber = 50;
System.out.println(findSquareRoot(1, inputNumber, inputNumber));
}
public static int findSquareRoot(int left, int right, int inputNumber){
// base condition
if (inputNumber ==0 || inputNumber == 1){
return inputNumber;
}
int mid = (left + right)/2;
// if square of mid value is less or equal to input value and
// square of mid+1 is less than input value. We found the answer.
if (mid*mid <= inputNumber && (mid+1)*(mid+1) > inputNumber){
return mid;
}
// if input number is greater than square of mid, we need
// to find in right hand side of mid else in left hand side.
if (mid*mid < inputNumber){
return findSquareRoot(mid+1, right, inputNumber);
}
else{
return findSquareRoot(left, mid-1, inputNumber);
}
}
}
Iterative binary solution:
public static double sqrt(int n) {
double low = 0;
double high = n;
double mid = (high - low) / 2;
while (Math.abs((mid * mid) - n) > 0.000000000001) {
if ((mid * mid) > n) {
high = mid;
mid = (high - low) / 2;
} else{
low = mid;
mid = mid + ((high - low) / 2);
}
}
return mid;
}
edst solution is good, but there is a mistake in line 11:
mid = (high - low) / 2;
should be
mid = low + (high - low) / 2;