1

I am trying to convert a C code to java, it's the Newton Raphson algorithm implementation. All is going well but there is a problem of pointers which were used in C code and i have removed them in java. The C code part is:

 x = newton(x_0, error, max_iters, &iters, &converged); //Call to a function (newton)

   if (converged) {

printf("Newton algorithm converged after %d steps.\n", iters);

    printf("The approximate solution is %19.16e\n", x);
    printf("f(%19.16e) = %19.16e\n", x, f(x));
   } else 
{

printf("Newton algorithm didn't converge after %d steps.\n", 
          iters);

    printf("The final estimate was %19.16e\n", x);
    printf("f(%19.16e) = %19.16e\n", x, f(x));
  }

and the function definition is something like this:

double newton(double x_0, double error, int max_iters, 
          int* iters_p, int* converged_p)

Now the problem is that, the values of two pointer variables are just zero every time. Also the if(converged) shows an error message of incomoatible types. required boolean, found int. Below is the java code so please help overcome this.

 //Member Functions///////
 public
            double function( double x) 
            { 
                return x*x - 2;
            }

            double F_Deriv( double x ) 
            {
                return 2.0*x; 
            }


            double newton(double x_0, double error, int max_iters,int iters, int converged) 
            {
   double x = x_0;
   double x_prev;
   int    iter = 0;

   do {
      iter++;
      x_prev = x;
      x = x_prev - function(x_prev)/F_Deriv(x_prev);
   } 
   while (Math.abs(x - x_prev) > error && iter < max_iters);

   if (Math.abs(x - x_prev) <= error)
      converged = 1;
   else
      converged = 0;
   iters = iter;

   return x;
} 


/////Main Function///////
    public static void main(String[] args) {

        Newton_Raphson obj=new Newton_Raphson();

        Scanner input=new Scanner(System.in);


        double x_0;       /* Initial guess                */
        double x;         /* Approximate solution         */
        double error;       /* Maximum error                */
        int    max_iters; /* Maximum number of iterations */
        int    iters;     /* Actual number of iterations  */
        int    converged; /* Whether iteration converged  */

        System.out.println( "Enter Initial Solution: " );
        x_0=input.nextDouble();

        System.out.println( "Enter Error: " );
        error=input.nextDouble();


        System.out.println( "Enter Maximum Iterations: " );
        max_iters=input.nextInt();

        x = obj.newton(x_0, error, max_iters, iters, converged);

        if(converged) 
        {
            System.out.println("Newton algorithm converged after "+ iters +" steps.");
            System.out.println("The approximate solution is "+ x);

        } 

        else 
        {
            System.out.println("Newton algorithm didn't converge after " + iters + " steps.");
            System.out.println("The final estimate was " + x);

        }

    }
codo
  • 45
  • 1
  • 9
  • 2
    If you dump that much code (which is by itself problematic), then please make sure it is readable and formatted properly. This isn't the case here. – Niklas B. May 02 '12 at 11:16

5 Answers5

3

Java passes arguments by value, so

if (Math.abs(x - x_prev) <= error)
    converged = 1;
else
    converged = 0;
iters = iter;

doesn't change the passed arguments for the caller. These changes never leave the called function.

The simplest way to mimick out-parameters, resp. passed pointers in C, is to pass a one-length array,

double newton(double x_0, double error, int[] max_iters,int iters, boolean[] converged)

and set (and query) iters[0] resp. converged[0].

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
1

One problem is that this statement:

if (Math.abs(x - x_prev) <= error)
   converged = 1;
else
   converged = 0;

is not doing anything because Java is pass by value. So it won't affect the value of converged outside the method. You could instead return an object from your method which would contain 2 members: x and converged:

return new NewtonResult (x, iters, converged);

with NewtonResult defined as:

public class NewtonResult {
    int x;
    int iters;
    boolean converged;
    NewtonResult (int x, int iters, boolean converged) {
        this.x = x;
        this.iters = iters;
        this.converged = converged;
    }
}

Another problem in your code is that Java if requires a boolean when you are passing an int, so you need to change your condition to:

if (converged != 0) {
    //
}

or even better make converged be a boolean.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • @codo This answer that you have accepted is essentially correct, but the type of `x` should be `double`. I imagine you already spotted that error. – David Heffernan May 02 '12 at 12:54
  • 1
    @DavidHeffernan That is correct - I was focusing on the methodology rather than the details of the implementation. – assylias May 02 '12 at 13:26
1

The problem is that converged and iters are returned from the original C code. The use of pointers for those parameters is so that the parameters can mimic out semantics. Since Java only supports pass by value, you cannot return that information in the same way using plain method parameters.

The other issue is that older versions of C do not have a boolean type and so int is used instead. The flag to indicate convergence should be a boolean in Java.

So your code needs to return three pieces of information: the result (a floating point value), converged (a boolean value) and iters (an integer). You should wrap these up into an object and return them that way.

The class you need would look like this:

public class NewtonResult {
     public boolean converged;
     public double value;
     public int iters;
}

You should change your newton method signature to be like so:

NewtonResult newton(double x_0, double error, int max_iters) 

Finally, I think that tolerance would be a much better name than error for that parameter.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • This answer is essentially correct, but the type of converged should be boolean (bool does not exist in java) ;-) – assylias May 02 '12 at 13:26
0

The class declaration is missing (public class Newton_Raphson...).

As said above, Java does not support arguments passed by reference, only by value, so you will need to wrap all those in a "Result" class.

public class Result {
     public int x;
     public int iters;
     public int converged; // better replace this with a boolean in Java
}

and change the return type of your method to that Result class.

You cannot test an int as a boolean. You should test that it is different from 0 (since in C everything different than 0 is considered as true). Or consider using a boolean directly, it's much easier.

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
0

When passing premitive types such as int, boolean- in java as method parameters and changing them, in reality they will not be changed.
The parmeters passed are the copy of the real ones (they are actually being passed by value).
Initialize objects out of the varaiables and then pass them to the methods as:

Integer[] a = new Integer[1];  // For int a
Boolean[] b = new Boolean[1];  // For boolean b
a[0] = 1;
b[0] = true;

This way the copy of the reference of the passed object will be passed, and when you change the value of one of its elements like [0] above, it will be also changed in the real variable.

GingerHead
  • 8,130
  • 15
  • 59
  • 93
  • 1
    Whilst you can do this, pretending that these parameters are arrays when they are not is the wrong solution. Clearly Java is terribly lacking in that it supports only pass by value, but faking it with arrays cannot be the best solution. – David Heffernan May 02 '12 at 11:47
  • @DavidHeffernan you are right about that. But in Java you have no other choice when passing variables as params. you can't win that! – GingerHead May 02 '12 at 12:29
  • The other choice is to pack all the out params into a class and return that. That's better. Even better would be to switch to C#! ;-) – David Heffernan May 02 '12 at 12:35
  • @DavidHeffernan the idea of packing is not bad I like it. – codo May 02 '12 at 12:53
  • @DavidHeffernan If you want to create a type (class) by yourself, then that's another choice, but eventually we're talking about the same thing (to pass objects no matter what the kind) at the end of the day ;-) – GingerHead May 02 '12 at 12:58
  • 1
    @JohnDoe Not really the same thing. The issue here is one of readability, clarity and maintainability. Obviously both approaches work. But only one of them clearly expresses intent. – David Heffernan May 02 '12 at 12:59
  • @DavidHeffernan OK, you win in terms of Neatness, Readability, Clarity and Maintainability, but in terms of **Quickness I win** ;-) – GingerHead May 02 '12 at 13:16
  • Why not just use `Integer` and `Boolean` instead of arrays. – mikek3332002 May 07 '12 at 01:05