Interpretable code using Newton-Raphson Method - java

I am having troubles with a Java code that must calculate the root square of a given parameter.
However,after some research I found a code that I don't know how was implemented properly.
// read in the command-line argument
double c = Double.parseDouble(args[0]);
double epsilon = 1.0e-15; // relative error tolerance
double t = c; // estimate of the square root of c
// repeatedly apply Newton update step until desired precision is achieved
while (Math.abs(t - c/t) > epsilon *t) {
t = (c/t + t) / 2.0;
}
// print out the estimate of the square root of c
System.out.println(t);
The first thing that I don't understand completely is why they are dividing by two on the 8th line.
t = (c/t + t) / 2.0;
The second thing which I do not understand is the condition from the while loop, to be more precise:
while(Math.abs(t - c/t) > epsilon*t)
Wouldn't be necessary to have only:
while(Math.abs(t - c/t) > epsilon)

t = (c/t + t) / 2.0;
This is used to calculate the average/mean of the two values c/t and t. The value is stored in the variable t for the next loop iteration. Use a System.out.println() call inside the while loop to check the values of t and c/t before this line and the values after this line.

Related

Java: method for an equation relevant to the Karplus-Strong equation does not return the anticipated result; unclear cause

In Part 1 of a prompt, I am expected to integrate an equation into Java to get the value for a period (T). The equation is as follows: T = FS / (440 * (2 ^(h/12))
NOTE:
FS = sample rate, which is 44100 / 1.
h = halfstep, which is provided by the user.
An example of this equation is: 44100 / (440 * (2 ^(2/12)) = 89.3
The code I wrote is as follows:
public static double getPeriod(int halfstep) {
double T = 100; // TODO: Update this based on note
double FS = 44100 / 1;
double power = Math.pow(2, (halfstep / 12));
double denominator = 440 * (power);
double result = (FS) / (denominator);
T = Math.round(result);
return T;
}
// Equation test.
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("halfstep is: ");
int halfstep = in.nextInt();
double period = getPeriod(halfstep);
System.out.print("Period: " + period + " ");
}
But when I run through this code with h = 2, T = 100.0 instead of the anticipated 89.3 and I am not sure what the issue is. Any thoughts on what's going on?
Because halfStep is an int, when you write
(halfstep / 12)
the calculation is done by taking halfStep / 12 and rounding down to the nearest integer. As a result, if you plug in 2 here, then halfStep / 12 will come back as 0 instead of 1/6. That's messing up the computation and is likely what's giving you the wrong answer.
You have a few options for how to proceed here. One would be to change halfStep to be a double rather than an int. Another would be to rewrite the division as
halfStep / 12.0
which, since 12.0 is a double literal, will perform the division in the way you intend.
One other potential issue - you declare the variable T as 100.0, but never use T anywhere in the calculation and ultimately overwrite it before returning it. I'm not sure whether this is intentional or whether that indicates that one of the formulas is incorrect.
Hope this helps!

How to print a DOUBLE with a variable INT

I'm doing my school homework and I got stuck. I set my variable as INT and now I can't change it because I'm using it for other calculations. Is there a way which I can print 3 numbers after the dot? I tried with printf and (double) but it didn't work.
This is my piece of code:
for (int i = 0; i < 2; i++) // Printing Inverse
{
System.out.print("[");
output.print("[");
for (int j = 0; j < 2; j++) {
sol[i][j] = adj[i][j] / det;
System.out.printf((double) sol[i][j] + " ");
output.print((double)sol[i][j] + " ");
}
}
By doing the calculation as a int, you are basically "throwing away" information. This means that from that point, it is not possible to get it back.
Since your current code looks like intVariable = intVariable / intVariable; print((double)intVariable), the compiler automatically uses integer division, what basically discards all decimals
You want your code to look like doubleVariable = intVariable / doubleVariable;print(doubleVariable), which would mean casting the divider in the division to a double, and changing the type of sol so it could hold doubles instead of the type you have now.
Is there a way which I can print 3 numbers after the dot? I tried with printf and (double) but it didn't work.
Well casting the int to double is not enough to get the expected output.
To print the casted double with three decimals, you need to use %3f as first parameter in the printf method, like this:
System.out.printf("%.3f", (double) sol[i][j]);
This is a live working demo.
Note:
Note that the result of the division in sol[i][j] = adj[i][j] / det; will be a double, so you need to declare your variables as double instead of int to avoid getting Exceptions.
I'm guessing that sol is a two-dimensional array of int, hence - as #B001 mentioned in his comment - it has no numbers after the decimal point. If all you want to do is print the result of the division: adj[i][j] / det as a double, I suggest using another variable just for printing the result, i.e.
double result = (double) adj[i][j] / det;
sol[i][j] = (int) result;
System.out.printf("%.3f", result);
I think you should redefine this variable again, that will not be catastrofic, just be carefull. Eclipse/NetBean will be notifying you if your variable has totally changed or not.
I am not sure, but I think that somewhere in Eclipse you could find a button that changes your variable and all its references.

Find the modo value

I have given a log value Y , i want to calculate the anti log of Y i.e
ans = (Math.pow(10,Y))%mod
where mod = 1e9+7 and the anti log of Y will always be integer i.e Y is calculate as follow Y= log(a) a is very large integer of range 10^100000
So for given Y i need to calculate ans ? How to do that considering the mod operation.
My Approach
double D = Y -(int)Y
long Pow = (long)Y
for(int i=1;i<=Pow;i++) ans = (ans*10)%mod;
ans = (ans*Math.pow(10,D))%mod
But it's not correct can someone suggest be efficient approach here ? BigDecimal can be useful there ?
For Example:
Y = 16.222122660468525
Using the straight forward method and rounding off i.e Math.log(10,Y) give me 1667718169966651 but using loops it's give me 16677181699666510. I am not using mod now just explaining that there is an error.
Here Y is small so direct method works and we can take mod easily. if Y is range of 10000 it will not work and overflow so we have to used mod.
I guess it's should work
double D = Y -(int)Y
long Pow = (long)Y
for(int i=1;i<=Pow;i++) ans = (ans*10)%mod;
ans = (ans*Math.pow(10,D))
ans = Math.round(ans)
ans%=mod
There is an error in your judgement here - the loop method is not at fault.
The value of a in your example has 17 integer digits. From this stackoverflow post, a double has ~16 significant digits of precision. Thus both the loop and direct calculations are in fact being limited by lack of precision.
(Just to confirm, using a high precision calculator, the value of a is 16677181699666650.8689546562984070600381634077.... Thus both of your values are incorrect - unless you copied them wrongly?)
Thus your loop method is not the problem; you just need a
higher-precision method to do the last step (calculating pow(10, frac(Y))).
As a side note, there is a more efficient way of doing the loop part - this post has more details.

Is this an effective while loop?

Here is an assignment:
"Let's say you are given a number, a, and you want to find its
square root. One way to do that is to start with a very rough guess about
the answer, x0, and then improve the guess using the following formula
x1 = (x0 + a/x0)/2
For example, if we want to find the square root of 9, and we start with x0 = 6,
then x1 = (6 + 9/6)/2 = 15/4 = 3.75, which is closer.
We can repeat the procedure, using x1 to calculate x2, and so on. In this
case, x2 = 3.075 and x3 = 3.00091. So that is converging very quickly on the
right answer(which is 3).
Write a method called squareRoot that takes a double as a parameter and
that returns an approximation of the square root of the parameter, using this
technique. You may not use Math.sqrt.
As your initial guess, you should use a/2. Your method should iterate until
it gets two consecutive estimates that differ by less than 0.0001; in other
words, until the absolute value is less than 0.0001. You can use
Math.abs to calculate the absolute value."
This is exercise meant to practice while loop. As you see I did the assignment, I think it works ? But I am not sure how did I come to solution ? In other words, what should I improve here ? Is there any other way to enter the loop differently ? How to name variables more appropriately ? And lastly, is my approach good or bad here ?
public class squareRoot {
public static void main(String args[]){
System.out.println(squareRoot(192.0));
}
public static double squareRoot(double a){
double gs = a/2; //guess
double ig = (gs + (a/gs))/2; //improving guess
double ig1 = (ig + (a/ig))/2; //one more improving guess, ig1
while (Math.abs((ig-ig1)) > 0.0001){ //with ig and ig1, I am entering the loop
ig = (ig1 + (a/ig1))/2;
ig1 = (ig + (a/ig))/2; //ig1 has to be less then ig
}
return ig1;
}
}
Your approach is nearly correct.
Let's talk about variables first. IMO, you should use full names for variables instead of acronyms. Use guess instead of gs. Use improvedGuess instead of ig etc.
Now that's out of the way we can see where your problem lies. For the while loop to finish, two consecutive guesses' difference must be less than 0.0001. However, here you are only comparing the 1st and 2nd guesses, the 3rd and 4th guesses, the 5th and 6th guesses etc. What if the 4th and 5th guesses' difference is less than 0.0001? Your loop won't stop. Instead, it returns the value of the 6th guess. Although it is more accurate, it does not fulfill the requirement.
Here's what I've come up with
public static double squareRoot(double a){
double guess = a/2;
double improvedGuess = (guess + (a/guess))/2;
while (Math.abs((guess - improvedGuess)) > 0.0001){
guess = improvedGuess;
improvedGuess = (guess + (a/guess))/2;
}
return improvedGuess;
}
Here is my Solution
private static double squareRoot(double a){
double x0= a/2;
while (true) {
double x1 = (x0 + a / x0) / 2;
if (Math.abs(x1 - x0) < 0.0001) {
break;
}
x0=x1;
}
return x0;
}

How to understand Newton's method for square root in Java?

public static double sqrt(double c)
{
if (c < 0) return Double.NaN;
double t = c; // line 1
double err = 1e-15; // line 2
while (Math.abs(t - c/t) > err * t) // line 3
t = (c/t + t) / 2.0; // line 4
return t;
}
Q1: I am confused by the variable t in line1 and line 4:
since t = c, then c/t = 1, what does line 4 mean?
Q2: In line 3, what's the purpose to check?
I searched "Newton's method" and got several explanation, but I still could not understand. May I request an straight forward explanation here?
Q1: Note that t changes with each iteration of the loop, so while c/t==1 initially, it won't after that.
Q2: We want the loop to continue until we get an answer "close enough", as defined by err.
The Newton's method is used to approximate real valued functions' roots. See here.
When you are calculating the root to a double value you are actually trying to solve for F(x) = X^2 - C where C is the double and you would be trying to find the x that makes the equation zero.
Now the Newton's Method approximates this by a series of guesses. By each guess(as this function has the appropriate properties), we get closer to the square root. The incremental approximation is actually calculating the tangent to the graph at each guess(t) and then choosing that as a guess at that point and moves closer in steps(c/t + t)/2. At a certain point we get very close and we don't want the function to go on forever so we have line 3 to check that our next estimation has a certain distance from the current approximation. If the next approximation is closer than err*t we don't bother continuing. We are close enough.

Categories

Resources