PSP:Personal Software Process – Lesson3

Facebook にシェア
このエントリーをはてなブックマークに追加
[`livedoor` not found]
Delicious にシェア

Lesson1, Lesson3に続いて、進めていきます。
各回のスクリプトはSoftware Engineering Instituteよりダウンロード可能です。

Lesson3: 「ファイルから数値データのリストを読み込み、相関係数と線形回帰パラメータを計算し、時間等の見積を行う」
● プログラム仕様スクリプト
ASGKIT PROG3を参照のこと

● 実行結果

β0: -22.54
β1: 1.7279
r: 0.9545
r2: 0.9111
y: 644.4294

● ソースコード

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * PSP Lesson3:
 * ファイルから数値データのリストを読み込み、相関係数と線形回帰パラメータを計算し、時間等の見積を行う
 */

public class Program3 {

	private int size;
	private double sumData1;
	private double sumData2;
	private double avgData1;
	private double avgData2;
	private double powData1;
	private double powData2;
	private double sumMulti;
	private double beta0;
	private double beta1;
	private double r;
	private double r2;
	private double y;

	public static void main(String[] args) {

		Program3 pg3 = new Program3();

		try {
			File f = new File(args[0]);
			FileInputStream fi = new FileInputStream(f);
			BufferedReader br = new BufferedReader(new InputStreamReader(fi,
					"UTF-8"));

			// 分析対象となるデータ行を指定する
			int data1 = Integer.parseInt(args[1]);
			int data2 = Integer.parseInt(args[2]);

			// 分析対象のLOC
			long num = Long.parseLong(args[3]);

			LinkedList<Double> linkData1 = new LinkedList<Double>();
			LinkedList<Double> linkData2 = new LinkedList<Double>();
			String line;
			while ((line = br.readLine()) != null) {
				String[] strrec = line.split("t");
				linkData1.add(Double.parseDouble(strrec[data1 - 1]));
				linkData2.add(Double.parseDouble(strrec[data2 - 1]));
			}
			pg3.size = linkData1.size();

			// 合計値を計算する
			pg3.sumData1 = pg3.calcSum(linkData1);
			pg3.sumData2 = pg3.calcSum(linkData2);

			// 合計値から平均値を計算する
			pg3.avgData1 = pg3.calcAvg(pg3.sumData1);
			pg3.avgData2 = pg3.calcAvg(pg3.sumData2);

			// X, Yの二乗の合計値、X*Yの合計値を計算する
			pg3.powData1 = pg3.calcSumPow(linkData1);
			pg3.powData2 = pg3.calcSumPow(linkData2);
			pg3.sumMulti = pg3.calcSumMulti(linkData1, linkData2);

			// β1 を計算する
			pg3.beta1 = pg3.calcBeta1();

			// β0 を計算する
			pg3.beta0 = pg3.calcBeta0();

			// R, R2 を計算する
			pg3.r = pg3.calcR();
			pg3.r2 = pg3.calcR2();

			// 最終的な結果を得る
			pg3.y = pg3.calcY(num);

			System.out.println("β0: " + pg3.beta0);
			System.out.println("β1: " + pg3.beta1);
			System.out.println("r: " + pg3.r);
			System.out.println("r2: " + pg3.r2);
			System.out.println("y: " + pg3.y);

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 合計値を計算する
	 * 
	 */
	private Double calcSum(LinkedList<Double> linkArray) {

		double sum = 0;
		for (Iterator i = linkArray.iterator(); i.hasNext();) {
			sum = sum + Double.parseDouble(i.next().toString());
		}

		return sum;

	}

	/**
	 * 平均値を計算する
	 * 
	 */
	private Double calcAvg(Double sum) {

		return this.changeScale(sum / size, 2);

	}

	/**
	 * X, Yの2乗合計値を計算する
	 * 
	 */
	private Double calcSumPow(LinkedList<Double> linkArray) {

		double sum = 0;
		for (Iterator i = linkArray.iterator(); i.hasNext();) {
			sum = sum + Math.pow(Double.parseDouble(i.next().toString()), 2);
		}

		return sum;

	}

	/**
	 * X*Yの合計値を計算する
	 * 
	 */
	private Double calcSumMulti(LinkedList<Double> linkData1,
			LinkedList<Double> linkData2) {

		double sum = 0;
		double i = 0;
		double j = 0;
		while (linkData1.size() != 0 || linkData2.size() != 0) {
			i = linkData1.pop();
			j = linkData2.pop();

			sum = sum + (i * j);
		}

		return sum;

	}

	/**
	 * β1 を計算する
	 * 
	 */
	private Double calcBeta1() {

		double num1 = (sumMulti - (size * avgData1 * avgData2));
		double num2 = (powData1 - (size * avgData1 * avgData1));

		return this.changeScale(num1 / num2, 4);

	}

	/**
	 * β0 を計算する
	 * 
	 */
	private Double calcBeta0() {

		return this.changeScale(avgData2 - (beta1 * avgData1), 2);

	}

	/**
	 * R を計算する
	 * 
	 */
	private Double calcR() {

		double num1 = (size * sumMulti) - (sumData1 * sumData2);

		double num21 = (size * powData1) - (sumData1 * sumData1);
		double num22 = (size * powData2) - (sumData2 * sumData2);

		return this.changeScale(num1 / (Math.sqrt(num21 * num22)), 4);

	}

	/**
	 * R2 を計算する
	 * 
	 */
	private Double calcR2() {

		return this.changeScale(r * r, 4);

	}

	/**
	 * Y を計算する
	 * 
	 */
	private Double calcY(long num) {

		return this.changeScale(beta0 + beta1 * num, 4);

	}

	/**
	 * 四捨五入を行う
	 * 
	 */
	private double changeScale(double val, int i) {

		BigDecimal bd = new BigDecimal(val);
		return bd.setScale(i, BigDecimal.ROUND_HALF_UP).doubleValue();

	}

}