2012-05-02 46 views
1

我想将C代码转换为java,它是牛顿拉夫森算法的实现。一切都很顺利,但是在C代码中使用的指针有问题,我已经在java中删除了它们。 C代码的部分是:指针和if语句错误,在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); 

     } 

    } 
+2

如果转储了很多代码(本身有问题),那么请确保它是可读的并且格式正确。这里不是这种情况。 –

+0

+1做得好 – GingerHead

回答

1

的一个问题是,这样的说法:

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

没有做任何事情,因为Java is pass by value。所以它不会影响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; 
    } 
} 

在你的代码的另一个问题是Java if需要一个boolean当你传递一个int,所以你需要改变你的条件:

if (converged != 0) { 
    // 
} 

甚至更​​好的使融合成为一个布尔值。

+0

@codo你接受的答案基本上是正确的,但'x'的类型应该是'double'。我想你已经发现了那个错误。 –

+1

@DavidHeffernan这是正确的 - 我关注的是方法而不是实现的细节。 – assylias

3

的Java按值传递参数,所以

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

不改变传递的参数为调用者。这些更改从不离开被调用的函数。

最简单的模拟输出参数的方法,用C传递指针,是通过一长阵列,

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

,并设置(和查询)iters[0] RESP。 converged[0]

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的所有东西都被认为是真的)。或者考虑直接使用布尔值,这更容易。

1

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

另一个问题是旧版本的C没有布尔类型,所以使用int代替。用于指示收敛的标志应该是Java中的boolean。所以你的代码需要返回三条信息:结果(浮点值),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

+0

这个答案基本上是正确的,但融合的类型应该是布尔值(bool不存在于java中);-) – assylias

+0

@assylias touche! –

0

当传递像int,boolean这样的前缀类型 - 在java中作为方法参数并更改它们时,实际上它们将不会被更改。
传递的参数是真实的副本(它们实际上是通过值传递的)。
初始化对象了varaiables,然后将它们传递给方法为:

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

这种方式传递的对象的引用的副本将被传递,而当你改变它的元素之一的值像上面的[0]一样,它也会在实变量中变化。

+1

对于不错的和完整的答案+1 – GingerHead

+1

虽然你可以做到这一点,但假如这些参数是非数组的参数是错误的解决方案。很明显,Java非常缺乏,它只支持按值传递,但用数组伪造它并不是最好的解决方案。 –

+0

@DavidHeffernan你说的对。但在Java中,当将变量作为参数传递时,您没有其他选择。你赢不了那个! – GingerHead