這個作業屬於哪個課程 | 軟體工程 |
---|---|
這個作業要求在哪裡 | 個人專案 |
這個作業的目標 | 完成個人專案,運用psp流程完成程式設計, 靈活使用測試工具和效能分析工具 |
專案GetHub
PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 30 | 30 |
Estimate | 估計這個任務需要多少時間 | 10 | 10 |
Development | 開發 | 900 | 600 |
Analysis | 需求分析 (包括學習新技術) | 30 | 60 |
Design Spec | 生成設計文件 | 30 | 30 |
Design Review | 設計複審 | 10 | 10 |
Coding Standard | 程式碼規範 (為目前的開發制定合適的規範) | 20 | 20 |
Design | 具體設計 | 60 | 50 |
Coding | 具體編碼 | 300 | 400 |
Code Review | 程式碼複審 | 20 | 20 |
Test | 測試(自我測試,修改程式碼,提交修改) | 60 | 60 |
Reporting | 報告 | 60 | 60 |
Test Repor | 測試報告 | 60 | 60 |
Size Measurement | 計算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事後總結, 並提出過程改進計劃 | 50 | 50 |
合計 | 1770 | 1460 |
計算模組介面的實現
1.simhash核心演算法介紹
2.透過idea底層原碼,利用java輸入輸出流引入文字物件
3.將文字中的文字轉換為字串,利用simhash演算法,逐個獲取雜湊值,漢明距離以及特徵值
計算模組介面部分的效能改進
1.效能圖
方法呼叫情況
2.CPU使用情況
3.覆蓋率
計算模組部分單元測試展示
1.主模組測試
點選檢視程式碼
package 部落格;
import java.text.Format;
public class test {
public static void main(String[] args) {
String origin="E:\\文件\\WeChat Files\\wxid_my9r0rap70vc22\\FileStorage\\File\\2024-03\\測試文字\\orig.txt";
String[] s={"E:\\文件\\WeChat Files\\wxid_my9r0rap70vc22\\FileStorage\\File\\2024-03\\測試文字\\orig_0.8_add.txt",
"E:\\文件\\WeChat Files\\wxid_my9r0rap70vc22\\FileStorage\\File\\2024-03\\測試文字\\orig_0.8_del.txt",
"E:\\文件\\WeChat Files\\wxid_my9r0rap70vc22\\FileStorage\\File\\2024-03\\測試文字\\orig_0.8_dis_1.txt",
"E:\\文件\\WeChat Files\\wxid_my9r0rap70vc22\\FileStorage\\File\\2024-03\\測試文字\\orig_0.8_dis_10.txt",
"E:\\文件\\WeChat Files\\wxid_my9r0rap70vc22\\FileStorage\\File\\2024-03\\測試文字\\orig_0.8_dis_15.txt"};
FileInput fileInput = new FileInput();
SimHashImpl hash1 = new SimHashImpl(fileInput.readString(origin), 64);
hash1.subByDistance(hash1, 3);
// 測試文件1
addTestOne(origin,s,fileInput,hash1);
// 測試文件2
addTestTwo(origin,s,fileInput,hash1);
// 測試文件3
addTestThree(origin,s,fileInput,hash1);
// 測試文件4
addTestFour(origin,s,fileInput,hash1);
// 測試文件5
addTestFive(origin,s,fileInput,hash1);
// 文件路徑不存在
addError(origin,s,fileInput,hash1);
}
private static void addError(String origin, String[] s, FileInput fileInput, SimHashImpl hash1) {
SimHashImpl hash2 = new SimHashImpl(fileInput.readString("orig.txt"), 64);
hash2.subByDistance(hash2, 3);
double distance = hash1.getDistance(hash1.getStrSimHash(),hash2.getStrSimHash());
System.out.println("該文章與原文相似度為:"+String.format("%.2f",(100-distance*100/128)) +"%");
}
private static void addTestFive(String origin, String[] s, FileInput fileInput, SimHashImpl hash1) {
SimHashImpl hash2 = new SimHashImpl(fileInput.readString(s[4]), 64);
hash2.subByDistance(hash2, 3);
double distance = hash1.getDistance(hash1.getStrSimHash(),hash2.getStrSimHash());
System.out.println("該文章與原文相似度為:"+String.format("%.2f",(100-distance*100/128)) +"%");
}
private static void addTestFour(String origin, String[] s, FileInput fileInput, SimHashImpl hash1) {
SimHashImpl hash2 = new SimHashImpl(fileInput.readString(s[3]), 64);
hash2.subByDistance(hash2, 3);
double distance = hash1.getDistance(hash1.getStrSimHash(),hash2.getStrSimHash());
System.out.println("該文章與原文相似度為:"+String.format("%.2f",(100-distance*100/128)) +"%");
}
private static void addTestThree(String origin, String[] s, FileInput fileInput, SimHashImpl hash1) {
SimHashImpl hash2 = new SimHashImpl(fileInput.readString(s[2]), 64);
hash2.subByDistance(hash2, 3);
double distance = hash1.getDistance(hash1.getStrSimHash(),hash2.getStrSimHash());
System.out.println("該文章與原文相似度為:"+String.format("%.2f",(100-distance*100/128)) +"%");
}
private static void addTestTwo(String origin, String[] s, FileInput fileInput, SimHashImpl hash1) {
SimHashImpl hash2 = new SimHashImpl(fileInput.readString(s[1]), 64);
hash2.subByDistance(hash2, 3);
double distance = hash1.getDistance(hash1.getStrSimHash(),hash2.getStrSimHash());
System.out.println("該文章與原文相似度為:"+String.format("%.2f",(100-distance*100/128)) +"%");
}
private static void addTestOne(String origin, String[] s, FileInput fileInput, SimHashImpl hash1) {
SimHashImpl hash2 = new SimHashImpl(fileInput.readString(s[0]), 64);
hash2.subByDistance(hash2, 3);
double distance = hash1.getDistance(hash1.getStrSimHash(),hash2.getStrSimHash());
System.out.println("該文章與原文相似度為:"+String.format("%.2f",(100-distance*100/128)) +"%");
}
}
點選檢視程式碼
package 部落格;
import java.io.*;
public class FileInput {
public String readString(String FI){
int len=0;
// 對字串進行多次修改,並且不會產生新的未產生的使用物件
// 建立一個
StringBuffer str=new StringBuffer("");
// File類以抽象類的方式代表檔名和目錄路徑名,用於檔案和目錄的建立,查詢和刪除
// FI代表需要插入檔案的目錄
// file獲取傳過來的路徑名,獲取檔案物件
File file = new File(FI);
// try{}當中利用readline來讀取檔案中的內容
try {
// FileInputStream()用於從檔案中讀取資料,他的物件用關鍵字new來建立
// 也可以使用一個檔案物件來建立一個輸入流隊形物件來讀取檔案
// File f=new File("C:/java/hello");
// InputStream in =new FileInputStream(f);
FileInputStream fileInputStream = new FileInputStream(file);
// 將讀取檔案中的內容賦給物件bufferedReader
// BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)))
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line=null;
// bufferedReader.readLine()從文字物件中讀取一行資料,見名知意,就是一行一行讀取
while((line=bufferedReader.readLine())!=null){
if (len!=0){
// 除了第一行,每一行都需要換行,str為StringBuffer類,多次新增資料
str.append("\r\n"+line);
// str.append(line);
}else {
str.append(line);
}
len++;
}
// System.out.println(len);
// 關閉此檔案輸入流並釋放與此流有關的所有系統資源
bufferedReader.close();
fileInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return str.toString();
// return str;
}
public static void main(String[] args) {
//
FileInput fileInput = new FileInput();
String s = fileInput.readString("E:\\文件\\WeChat Files\\wxid_my9r0rap70vc22\\FileStorage\\File\\2024-03\\測試文字\\orig.txt");
System.out.println(s);
}
}
點選檢視程式碼
public BigInteger simHash() {
// 定義特徵向量/陣列
int[] v = new int[this.hashbits];
StringTokenizer stringTokens = new StringTokenizer(this.tokens);
while (stringTokens.hasMoreTokens()) {
String temp = stringTokens.nextToken();
//2、將每一個分詞hash為一組固定長度的數列.比如 64bit 的一個整數.
BigInteger t = this.hash(temp);
for (int i = 0; i < this.hashbits; i++) {
BigInteger bitmask = new BigInteger("1").shiftLeft(i);
// 3、建立一個長度為64的整數陣列(假設要生成64位的數字指紋,也可以是其它數字),
// 對每一個分詞hash後的數列進行判斷,如果是1000...1,那麼陣列的第一位和末尾一位加1,
// 中間的62位減一,也就是說,逢1加1,逢0減1.一直到把所有的分詞hash數列全部判斷完畢.
if (t.and(bitmask).signum() != 0) {
v[i] += 1;
} else {
v[i] -= 1;
}
}
}
BigInteger fingerprint = new BigInteger("0");
StringBuffer simHashBuffer = new StringBuffer();
for (int i = 0; i < this.hashbits; i++) {
// 4、最後對陣列進行判斷,大於0的記為1,小於等於0的記為0,得到一個 64bit 的數字指紋/簽名.
if (v[i] >= 0) {
fingerprint = fingerprint.add(new BigInteger("1").shiftLeft(i));
simHashBuffer.append("1");
}else{
simHashBuffer.append("0");
}
}
this.strSimHash = simHashBuffer.toString();
setStrSimHash(strSimHash);
// System.out.println(this.strSimHash + " length " + this.strSimHash.length());
return fingerprint;
}