第六章

反覆

while 迴圈

複利投資

投資 $10,000, 5% 利率, 按年複利計息
Year
Balance
0
$10,000
1
$10,500
2
$11,025
3
$11,576.25
4
$12,155.06
5
$12,762.82

幾年後本利和至少有 $20,000?

while 敘述

while (condition)
   statement;


當條件滿足時重覆執行敘述

while (balance < targetBalance)
{
   year++;
   double interest = balance * rate / 100;
   balance = balance + interest;
}

File Investment.java


/**
   A class to monitor the growth of an investment that
   accumulates interest at a fixed annual rate
*/
public class Investment
{
   /**
      Constructs an Investment object from a starting balance and
      interest rate.
      @param aBalance the starting balanece
      @param aRate the interest rate in percent
   */
   public Investment(double aBalance, double aRate)
   {
      balance = aBalance;
      rate = aRate;
      years = 0;
   }

   /**
      Keeps accumulating interest until a target balance has
      been reached.
      @param targetBalance the desired balance
   */
   public void waitForBalance(double targetBalance)
   {
      while (balance < targetBalance)
      {
         years++;
         double interest = balance * rate / 100;
         balance = balance + interest;
      }
   }

   /**
      Gets the current investment balance.
      @return the current balance
   */
   public double getBalance()
   {
      return balance;
   }

   /**
      Gets the number of years this investment has accumulated
      interest.
      @return the number of years since the start of the investment
   */
   public int getYears()
   {
      return years;
   }

   private double balance;
   private double rate;
   private int years;
}


File InvestmentTest.java


/**
   This program computes how long it takes for an investment
   to double.
*/
public class InvestmentTest
{
   public static void main(String[] args)
   {
      final double INITIAL_BALANCE = 10000;
      final double RATE = 5;
      Investment invest = new Investment(INITIAL_BALANCE, RATE);
      invest.waitForBalance(2 * INITIAL_BALANCE);
      int years = invest.getYears();
      System.out.println("The investment doubled after "
         + years + " years");
   }
}


while 迴圈流程圖



Syntax 6.1. while 敘述

  while (condition)
   statement

例題:

 
while (balance < targetBalance)
{
   year++;
   double interest = balance * rate / 100;
   balance = balance + interest;
}

用途:

當條件滿足時重覆執行敘述

常見錯誤: 無窮迴圈

while (year < 20)

   balance = balance +
      balance * rate / 100; 
}

while (year > 0)

   year++; // oops, meant --
   . . .
}

迴圈永遠重覆執行--必須停掉程式

常見錯誤: Off-by-1 錯誤

避免 Off-by-1 錯誤


do 敘述

執行迴圈主體至少一次:
do 
statement
while (condition);

例題: 輸入確認(Validate)

double value;
do
{
String input = JOptionPane.showInputDialog(
"Please enter a positive number");
value = Integer.parseInt(input);
}
while (input <= 0);

do 迴圈流程圖


6.2 for 迴圈

for 敘述

for 迴圈流程圖


File Investment.java


/**
   A class to monitor the growth of an investment that
   accumulates interest at a fixed annual rate
*/
public class Investment
{
   /**
      Constructs an Investment object from a starting balance and
      interest rate.
      @param aBalance the starting balanece
      @param aRate the interest rate in percent
   */
   public Investment(double aBalance, double aRate)
   {
      balance = aBalance;
      rate = aRate;
      years = 0;
   }

   /**
      Keeps accumulating interest until a target balance has
      been reached.
      @param targetBalance the desired balance
   */
   public void waitForBalance(double targetBalance)
   {
      while (balance < targetBalance)
      {
         years++;
         double interest = balance * rate / 100;
         balance = balance + interest;
      }
   }

   /**
      Keeps accumulating interest for a given number of years.
      @param n the number of years
   */
   public void waitYears(int n)
   {
      for (int i = 1; i <= n; i++)
      {
         double interest = balance * rate / 100;
         balance = balance + interest;
      }
      years = years + n;
   }

   /**
      Gets the current investment balance.
      @return the current balance
   */
   public double getBalance()
   {
      return balance;
   }

   /**
      Gets the number of years this investment has accumulated
      interest.
      @return the number of years since the start of the investment
   */
   public int getYears()
   {
      return years;
   }

   private double balance;
   private double rate;
   private int years;
}


File InvestmentTest.java


/**
   This program computes how much an investment grows in
   a given number of years.
*/
public class InvestmentTest
{
   public static void main(String[] args)
   {
      final double INITIAL_BALANCE = 10000;
      final double RATE = 5;
      final int YEARS = 20;
      Investment invest = new Investment(INITIAL_BALANCE, RATE);
      invest.waitYears(YEARS);
      double balance = invest.getBalance();
      System.out.println("The balance after " + YEARS +
         " years is " + balance);
   }
}


Syntax 6.2. for 敘述

  for (initialization; condition; update )
   statement

例題:

  for (int i = 1; i <= n; i++)
{
   double interest = balance * rate / 100;
   balance = balance + interest;
}

用途:

To execute an initialization, then keep executing a statement and updating an expression while a condition is true

常見錯誤: Semicolons

6.3 多層迴圈

File Triangle.java


/**
   This class describes triangle objects that can be displayed
   as shapes like this:
   []
   [][]
   [][][]
*/
public class Triangle
{
   /**
      Constructs a triangle.
      @param aWidth the number of [] in the last row of the triangle.
   */
   public Triangle(int aWidth)
   {
      width = aWidth;
   }

   /**
      Computes a string representing the triangle.
      @return a string consisting of [] and newline characters
   */
   public String toString()
   {
      String r = "";
      for (int i = 1; i <= width; i++)
      {
         // make triangle row
         for (int j = 1; j <= i; j++)
            r = r + "[]";
         r = r + "\n";
      }
      return r;
   }

   private int width;
}


File TriangleTest.java


/**
   This program tests the Triangle class.
*/
public class TriangleTest
{
   public static void main(String[] args)
   {
      Triangle small = new Triangle(3);
      System.out.println(small.toString());

      Triangle large = new Triangle(15);
      System.out.println(large.toString());
   }
}


6.4 處理輸入

6.4.1 讀取輸入數值

一般模型:
boolean done = false;
while (!done)
{
String input = read input;
if (end of input indicated)
done = true;
else
{
process input
}
}

這個模型稱為 "Loop and a half"

File DataSet.java


/**
   Computes the average of a set of data values.
*/
public class DataSet
{
   /**
      Constructs an empty data set.
   */
   public DataSet()
   {
      sum = 0;
      count = 0;
      maximum = 0;
   }

   /**
      Adds a data value to the data set
      @param x a data value
   */
   public void add(double x)
   {
      sum = sum + x;
      if (count == 0 || maximum < x) maximum = x;
      count++;
   }

   /**
      Gets the average of the added data.
      @return the average or 0 if no data has been added
   */
   public double getAverage()
   {
      if (count == 0) return 0;
      else return sum / count;
   }

   /**
      Gets the largest of the added data.
      @return the maximum or 0 if no data has been added
   */
   public double getMaximum()
   {
      return maximum;
   }

   private double sum;
   private double maximum;
   private int count;
}


File InputTest.java


import javax.swing.JOptionPane;

/**
   This program computes the average and maximum of a set
   of input values.
*/
public class InputTest
{
   public static void main(String[] args)
   {
      DataSet data = new DataSet();

      boolean done = false;
      while (!done)
      {
         String input = JOptionPane.showInputDialog("Enter value, Cancel to quit");
         if (input == null)
            done = true;
         else
         {
            double x = Double.parseDouble(input);
            data.add(x);
         }
      }

      System.out.println("Average = " + data.getAverage());
      System.out.println("Maximum = " + data.getMaximum());
      System.exit(0);
   }
}


6.4.2 String Tokenization

File InputTest.java


import java.util.StringTokenizer;
import javax.swing.JOptionPane;

/**
   This program computes the average and maximum of a set
   of input values that are entered on a single line.
*/
public class InputTest
{
   public static void main(String[] args)
   {
      DataSet data = new DataSet();

      String input = JOptionPane.showInputDialog("Enter values:");
      StringTokenizer tokenizer = new StringTokenizer(input);
      while (tokenizer.hasMoreTokens())
      {
         String token = tokenizer.nextToken();

         double x = Double.parseDouble(token);
         data.add(x);
      }

      System.out.println("Average = " + data.getAverage());
      System.out.println("Maximum = " + data.getMaximum());
      System.exit(0);
   }
}


6.4.3 造訪字串中的字元

6.5 亂數(Random Number)


File Die.java


import java.util.Random;

/**
   This class models a die that, when cast, lands on a random
   face.
*/
public class Die
{
   /**
      Constructs a die with a given number of sides
      @param s the number of sides, e.g. 6 for a normal die
   */
   public Die(int s)
   {
      sides = s;
      generator = new Random();
   }

   /**
      Simulates a throw of the die
      @return the face of the die
   */
   public int cast()
   {
      return 1 + generator.nextInt(sides);
   }


   private Random generator;
   private int sides;
}


File DieTest.java


/**
   This program simulates casting a die ten times.
*/
public class DieTest
{
   public static void main(String[] args)
   {
      Die d = new Die(6);
      final int TRIES = 10;
      for (int i = 1; i <= TRIES; i++)
      {
         int n = d.cast();
         System.out.print(n + " ");
      }
      System.out.println();
   }
}


Buffon Needle Experiment


Needle Position


File Needle.java


import java.util.Random;

/**
   This class simulates a needle in the Buffon needle experiment.
*/
public class Needle
{
   /**
      Constructs a needle.
   */
   public Needle()
   {
      hits = 0;
      tries = 0;
      generator = new Random();
   }

   /**
      Drops the needle on the grid of lines and
      remembers whether the needle hit a line.
   */
   public void drop()
   {
      double ylow = 2 * generator.nextDouble();
      double angle = 180 * generator.nextDouble();

      // compute high point of needle

      double yhigh = ylow + Math.sin(Math.toRadians(angle));
      if (yhigh >= 2) hits++;
      tries++;
   }

   /**
      Gets the number of times the needle hit a line.
      @return the hit count
   */
   public int getHits()
   {
      return hits;
   }

   /**
      Gets the total number of times the needle was dropped.
      @return the try count
   */
   public int getTries()
   {
      return tries;
   }

   private Random generator;
   private int hits;
   private int tries;
}


File NeedleTest.java


/**
   This program simulates the Buffon needle experiment
   and prints the resulting approximations of pi.
*/
public class NeedleTest
{
   public static void main(String[] args)
   {
      Needle n = new Needle();
      final int TRIES1 = 10000;
      final int TRIES2 = 100000;

      for (int i = 1; i <= TRIES1; i++)
         n.drop();
      System.out.println("Tries / Hits = "
         + (double)n.getTries() / n.getHits());

      for (int i = TRIES1 + 1; i <= TRIES2; i++)
         n.drop();
      System.out.println("Tries / Hits = "
         + (double)n.getTries() / n.getHits());
   }
}