1

我正在尝试将 C 代码转换为 java,它是 Newton Raphson 算法实现。一切进展顺利,但存在 C 代码中使用的指针问题,我已在 java 中删除了它们。C代码部分是:

 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));
  }

函数定义是这样的:

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

现在的问题是,两个指针变量的值每次都为零。if(converged) 还显示了不兼容类型的错误消息。必需的布尔值,找到 int。下面是java代码,所以请帮助克服这个问题。

 //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);

        }

    }
4

5 回答 5

3

Java 按值传递参数,所以

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

不会更改调用者传递的参数。这些更改永远不会离开被调用的函数。

模仿输出参数的最简单方法,resp。在 C 中传递指针是传递一个长度为一长度的数组,

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

并设置(和查询)iters[0]resp。converged[0].

于 2012-05-02T11:19:50.133 回答
1

一个问题是这个声明:

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

没有做任何事情,因为Java 是按值传递的。所以不会影响converged方法外的值。您可以改为从您的方法中返回一个对象,该对象将包含 2 个成员:x 和收敛:

return new NewtonResult (x, iters, converged);

NewtonResult 定义为:

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;
    }
}

代码中的另一个问题是 Javaif在传递 int 时需要布尔值,因此您需要将条件更改为:

if (converged != 0) {
    //
}

甚至更好地使收敛为布尔值。

于 2012-05-02T11:18:42.433 回答
1

问题是,converged并且iters是从原始 C 代码返回的。对这些参数使用指针是为了使参数可以模仿out语义。由于 Java 仅支持按值传递,因此您无法使用普通方法参数以相同的方式返回该信息。

另一个问题是旧版本的 C 没有布尔类型,因此int被使用。boolean表示收敛的标志在 Java 中应该是 a 。

所以你的代码需要返回三个信息:结果(一个浮点值)、converged(一个布尔值)和iters(一个整数)。您应该将它们包装成一个对象并以这种方式返回它们。

您需要的课程如下所示:

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

您应该将newton方法签名更改为:

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

最后,我认为这tolerance将是一个比error该参数更好的名称。

于 2012-05-02T11:22:52.007 回答
0

缺少类声明(公共类 Newton_Raphson...)。

如上所述,Java 不支持通过引用传递的参数,只支持通过值传递,因此您需要将所有这些都包装在“Result”类中。

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

并将您的方法的返回类型更改为该 Result 类。

您不能将 int 测试为布尔值。您应该测试它是否不同于 0(因为在 C 中,所有不同于 0 的东西都被认为是真的)。或者考虑直接使用布尔值,它会容易得多。

于 2012-05-02T11:22:16.297 回答
0

当在 java 中将诸如int, boolean- 之类的原始类型作为方法参数传递并更改它们时,实际上它们不会被更改。
传递的参数是真实参数的副本(它们实际上是按值传递的)。
从变量中初始化对象,然后将它们传递给方法:

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

这样,传递对象的引用副本将被传递,并且当您像[0]上面那样更改其中一个元素的值时,它也会在真实变量中更改。

于 2012-05-02T11:30:49.137 回答