2013-05-13 161 views
4

這是一個家庭作業問題。我無法轉換成如下遞歸函數:將循環轉換爲遞歸函數

public class Integrate { 
    public static double integrate(int a, int b, int steps) 
    { 
     double sum=0; 
     double delta = 1.0 * (b - a)/steps; 
     double x = a; 
     double f = 0.5*x*x + 3*x + 5; 

     for (int i = 0; i< steps; i++) 
     { 
      x = x + delta; 
      double fr = 0.5*x*x + 3*x + 5; 
      double area = f * delta + 0.5*(fr - f)*delta; 
      sum += area; 
      f = fr; 
     } 
     return sum; 
    } 
    public static void main(String [] args) 
    { 
     int a, b, step; 
     a = Integer.parseInt(args[0]); 
     b = Integer.parseInt(args[1]); 
     step = Integer.parseInt(args[2]); 
     System.out.format("Integral is %f\n", integrate(a,b,step)); 
    } 
} 

這是我迄今爲止,但輸出是不一樣的原代碼。我無法弄清楚什麼是錯的

public class Integrate { 

    public static double integrate(int a, int b, int steps) { 
     double sum=0; 
     int i=0; 
     sum = rintegrate(a, b, steps, i, sum); 
     return sum; 
    } 

    public static double rintegrate(int a, int b, int steps, 
      int i, double sum) { 
     double delta = 1.0 * (b - a)/steps; 
     double x = a; 
     double f = 0.5*x*x + 3*x + 5; 
     if (i<steps) { 
      x = x + delta; 
      double fr = 0.5*x*x + 3*x + 5; 
      double area = f * delta + 0.5*(fr - f)*delta; 
      sum += area; 
      f = fr; 
      i++; 
      rintegrate(a, b, steps, i, sum); 
     } 
     return sum; 
    } 

    public static void main(String[] args) { 
     int a, b, step; 
     a = Integer.parseInt(args[0]); 
     b = Integer.parseInt(args[1]); 
     step = Integer.parseInt(args[2]); 
     System.out.format("Integral is %f\n", integrate(a,b,step)); 
    } 

} 
+0

什麼是你的原碼輸出?以及新代碼的輸出是什麼? – 2013-05-13 16:11:34

+3

看起來你沒有使用你的'rintegrate'的遞歸值遞歸地... – 2013-05-13 16:12:10

+0

a = 1,b = 10,step = 1000 .......原來出來360.000061和我的輸出0.076662 – user2378481 2013-05-13 16:15:30

回答

3

我不打算全面分析這個問題,但這裏有一些意見,我有間sum += area;return sum;是多餘的

if (i<steps) { 
     x = x + delta; 
     double fr = 0.5*x*x + 3*x + 5; 
     double area = f * delta + 0.5*(fr - f)*delta; 
     sum += area; 
     f = fr; 
     i++; 
     rintegrate(a, b, steps, i, sum); 
    } 
    return sum; 

一切。

  • 你設置ffr,但你從來沒有使用後f。如果你想f下次不同,也許你可以將它作爲參數傳遞給你的遞歸函數
  • 你遞歸地調用rintegrate(...),但是你沒有對它返回的值做任何事情。你可能想要使用該值。

你應該考慮遞歸作爲使用問題的一個較小的版本來解決本身。

這裏是你的問題,假設你有一個函數一些代碼:segment,只是計算給出a第一段的大小,delta

rintegrate(a, b, steps) 
{ 
    if(steps <= 1) 
    { 
     delta = b-a; 
     return segment(a, delta) 
    } 
    else 
    { 
     delta = (b-a)/steps 
     return segment(a, delta) + rintegrate(a+delta, b, steps-1) 
    } 
} 
+0

你的榜樣刪除代碼,它與步驟計算,然後下去?有沒有辦法做到這一點從0開始? – user2378481 2013-05-13 16:50:56

+0

@ user2378481你仍然在反覆思考這個問題。嘗試遞歸思考問題。您的功能需要添加一個細分,並添加到其他細分的總和中,然後返回該值 – 2013-05-13 16:53:07

+0

這仍然很難理解。這是否像繼續前一步的一切?對不起,遞歸對我來說看起來像一個循環。 – user2378481 2013-05-13 17:06:26

1

工作版本

只要複製粘貼你會得到與你原來的方法相同的輸出。

public static void main(String[] args) { 
     int a = 1, b = 10, step = 1000; 
      double delta = 1.0 * (b - a)/step; 
     double sum = integrate(a, b, step, 0, 0, 0, delta); 
     double test = working(a, b, step); 
     System.out.println("Integral is " + sum); 
     System.out.println("Integral is " + test); 
    } 

工作遞歸版本:

public static double integrate(double x, int b, int steps, int i, 
      double sum, double f, double delta) { 
     f = 0.5 * x * x + 3 * x + 5; 
     if (i < steps) { 
      x = x + delta; 
      double fr = 0.5 * x * x + 3 * x + 5; 
      double area = f * delta + 0.5 * (fr - f) * delta; 
      return integrate(x, b, steps, i + 1, sum + area, fr, delta); 
     } 
     return sum; 
    } 

你原來的迭代方法;

public static double working(int a, int b, int steps) { 
    double sum = 0; 
    double delta = 1.0 * (b - a)/steps; 
    double x = a; 
    double f = 0.5 * x * x + 3 * x + 5; 

    for (int i = 0; i < steps; i++) { 
     x = x + delta; 
     double fr = 0.5 * x * x + 3 * x + 5; 
     double area = f * delta + 0.5 * (fr - f) * delta; 
     sum += area; 
     f = fr; 
    } 
    return sum; 
} 
+0

的基本情況嗨,謝謝你的幫助。你的代碼也沒有給出正確的輸出。 hw問題被稱爲整合的整合,這就是爲什麼我首先使用了整合方法。 – user2378481 2013-05-13 16:44:55

+0

我明白了。你的作品現在。這有點不是我在找的東西,但有助於看到我的問題。我不明白你的版本在哪裏計算三角洲? – user2378481 2013-05-13 17:09:59

+0

謝謝,我現在有一個工作解決方案,通過在遞歸方法之外聲明delta和x。但是,爲什麼他們之間的調用會有所不同,如果沒有與它們相關的變量被改變? – user2378481 2013-05-13 17:33:54

0

這是你想要的東西;)

public class Integrate{ 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     int a, b, step; 
     a = Integer.parseInt(args[0]); 
     b = Integer.parseInt(args[1]); 
     step = Integer.parseInt(args[2]); 
     System.out.format("Integral is %f\n", 
       adaptiveSimpsons(a, b, step)); 

    } 

    private static double f(double i) { 
     return (0.5 * i * i + 3 * i + 5); 
    } 

    static double adaptiveSimpsons(double a, double b, // interval [a,b] 
      int maxRecursionDepth) { // recursion cap 
     double c = (a + b)/2, h = b - a; 
     double fa = f(a), fb = f(b), fc = f(c); 
     double S = (h/6) * (fa + 4 * fc + fb); 
     return adaptiveSimpsonsAux(a, b, S, fa, fb, fc, maxRecursionDepth); 
    } 

    private static double adaptiveSimpsonsAux(double a, double b, double S, double fa, 
      double fb, double fc, int bottom) { 
     double c = (a + b)/2, h = b - a; 
     double d = (a + c)/2, e = (c + b)/2; 
     double fd = f(d), fe = f(e); 
     double Sleft = (h/12) * (fa + 4 * fd + fc); 
     double Sright = (h/12) * (fc + 4 * fe + fb); 
     double S2 = Sleft + Sright; 
     if (bottom <= 0) 
      return S2 + (S2 - S)/15; 
     return adaptiveSimpsonsAux(a, c, Sleft, fa, fc, fd, bottom - 1) 
       + adaptiveSimpsonsAux(c, b, Sright, fc, fb, fe, bottom - 1); 
    } 
} 

測試和工作

轉換過來的C代碼中給出here

+0

我認爲你在錯誤的地方 – user2378481 2013-05-13 17:07:00

+0

不,你正在嘗試做遞歸整合可以遞歸使用辛普森算法來進行登載,因此該方法被命名的方式。你甚至看過代碼嗎?如OP中所述,它遞歸地將函數0.5x^2 + 3x + 5集成到給定數量的步驟。如果您將我的代碼複製到eclipse並運行它,您會看到它遞歸計算所需的積分... – o0rebelious0o 2013-05-13 17:11:52