ComputePi
Home ] Up ] ComputeEngineImpl ] Security Policies ] [ ComputePi ] ComputeEngineClient ] Running the Example ]

 

 

Now, here's a compute class, ComputePi, that computes the value of π to a specified number of places:

package rmiClient;

import java.io.Serializable;
import java.math.BigDecimal;

import rmi.Task;

/**
 * Class to compute the value of Pi
 *
 * (Based on the client.Pi class in the Java RMI Tutorial, at
 *  http://java.sun.com/docs/books/tutorial/rmi/client.html )
 */
public class ComputePi implements Task<BigDecimal>, Serializable
{
  /**
   * Construct a task to calculate pi to the specified
   * precision.
   * @param digits the precision
   */
  public ComputePi(int digits)
  {
    m_digits = digits;
  }
  
  /**
   * Calculate pi.
   */
  public BigDecimal execute()
  {
    return computePi(m_digits);
  }
  
  /**
   * Compute the value of pi to the specified number of
   * digits after the decimal point.  The value is
   * computed using Machin's formula:
   *
   *          pi/4 = 4*arctan(1/5) - arctan(1/239)
   *
   * and a power series expansion of arctan(x) to
   * sufficient precision.
   *
   * @param digits the number of digits of precision
   */
  public static BigDecimal computePi(int digits)
  {
    int scale = digits + 5;
    BigDecimal arctan1_5 = arctan(5, scale);
    BigDecimal arctan1_239 = arctan(239, scale);
    BigDecimal pi = arctan1_5.multiply(FOUR)
                             .subtract(arctan1_239)
                             .multiply(FOUR);
    return pi.setScale(digits, BigDecimal.ROUND_HALF_UP);
  }
  
  /**
   * Compute the value, in radians, of the arctangent of
   * the inverse of the supplied integer to the specified
   * number of digits after the decimal point.  The value
   * is computed using the power series expansion for the
   * arc tangent:
   *
   * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + (x^9)/9 ...
   */
  public static BigDecimal arctan(int inverseX, int scale)
  {
    BigDecimal result, numerator, term;
    BigDecimal invX = BigDecimal.valueOf(inverseX);
    BigDecimal invX2 = BigDecimal.valueOf(inverseX * inverseX);
    
    numerator = BigDecimal.ONE.divide(invX, scale, ROUNDING_MODE);
    
    result = numerator;
    int i = 1;
    do
    {
      numerator = numerator.divide(invX2, scale, ROUNDING_MODE);
      int denominator = 2 * i + 1;
      term = numerator.divide(BigDecimal.valueOf(denominator),
                              scale, ROUNDING_MODE);
      if ((i % 2) != 0)
      {
        result = result.subtract(term);
      }
      else
      {
        result = result.add(term);
      }
      i++;
    } while (term.compareTo(BigDecimal.ZERO) != 0);
    return result;
  }
  
  ///// Private data /////
    
  private static final long serialVersionUID = 227L;
  
  /** constants used in pi computation */
  private static final BigDecimal FOUR = BigDecimal.valueOf(4);
  
  /** rounding mode to use during pi computation */
  private static final int ROUNDING_MODE = BigDecimal.ROUND_HALF_EVEN;
  
  /** digits of precision after the decimal point */
  private final int m_digits;
}

Note that it uses the java.math.BigDecimal class to maintain accuracy and precision.

 
The page was last updated February 19, 2008