diff --git a/WindowsFormsApp6/Form1.cs b/WindowsFormsApp6/Form1.cs
index dcedfc6..90f7efc 100644
--- a/WindowsFormsApp6/Form1.cs
+++ b/WindowsFormsApp6/Form1.cs
@@ -378,25 +378,36 @@ namespace WindowsFormsApp6
return;
// 计算并添加/更新平均值行
- var averages = CalculateAverages();
- UpdateAverageRow(averages);
+ UpdateAverageRow(null);
// 刷新界面
RefreshDataGridView();
}
///
- /// 计算各试样的平均值
+ /// 计算所有试样的总平均值
///
- private double[] CalculateAverages()
+ private double CalculateOverallAverage()
{
- var averages = new double[currentSampleCount];
- for (int i = 1; i <= currentSampleCount; i++)
+ var timeRows = sampleDataTable.AsEnumerable()
+ .Where(r => r.Field("序号") == TIME_ROW_LABEL);
+
+ if (!timeRows.Any())
+ return 0;
+
+ double sum = 0;
+ int count = 0;
+
+ foreach (var row in timeRows)
{
- averages[i - 1] = sampleDataTable.AsEnumerable()
- .Average(r => r.Field($"试样{i}"));
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ sum += row.Field($"试样{i}");
+ count++;
+ }
}
- return averages;
+
+ return count > 0 ? sum / count : 0;
}
///
@@ -406,23 +417,35 @@ namespace WindowsFormsApp6
{
var avgRows = sampleDataTable.Select($"序号 = '{AVG_ROW_LABEL}'");
+ // 计算总平均值
+ double overallAvg = CalculateOverallAverage();
+
if (avgRows.Length == 0)
{
// 添加新的平均值行
DataRow avgRow = sampleDataTable.NewRow();
avgRow["序号"] = AVG_ROW_LABEL;
- for (int i = 0; i < currentSampleCount; i++)
+
+ // 只在第一列显示总平均值
+ avgRow["试样1"] = overallAvg;
+
+ // 其他列设置为空
+ for (int i = 2; i <= currentSampleCount; i++)
{
- avgRow[$"试样{i + 1}"] = averages[i];
+ avgRow[$"试样{i}"] = DBNull.Value;
}
+
sampleDataTable.Rows.Add(avgRow);
}
else
{
// 更新现有平均值行
- for (int i = 0; i < currentSampleCount; i++)
+ avgRows[0]["试样1"] = overallAvg;
+
+ // 其他列设置为空
+ for (int i = 2; i <= currentSampleCount; i++)
{
- avgRows[0][$"试样{i + 1}"] = averages[i];
+ avgRows[0][$"试样{i}"] = DBNull.Value;
}
}
}
@@ -580,25 +603,24 @@ namespace WindowsFormsApp6
int rowIndex = sheet.LastRowNum + 1;
IRow avgRow = sheet.CreateRow(rowIndex);
- avgRow.CreateCell(0).SetCellValue(AVG_ROW_LABEL);
+
+ // 序号列
+ ICell labelCell = avgRow.CreateCell(0);
+ labelCell.SetCellValue(AVG_ROW_LABEL);
+ labelCell.CellStyle = avgStyle;
- double[] averages = new double[currentSampleCount];
- for (int i = 1; i <= currentSampleCount; i++)
+ // 计算总平均值
+ double overallAvg = CalculateOverallAverage();
+
+ // 在第一个试样列显示总平均值
+ ICell avgCell = avgRow.CreateCell(1);
+ avgCell.SetCellValue(overallAvg);
+ avgCell.CellStyle = avgStyle;
+
+ // 合并所有试样列
+ if (currentSampleCount > 1)
{
- averages[i - 1] = dataRows.Average(r => r.Field($"试样{i}"));
- avgRow.CreateCell(i).SetCellValue(averages[i - 1]);
- }
-
- // 不再添加总平均值到时间列
-
- // 应用样式
- for (int i = 0; i <= currentSampleCount; i++)
- {
- var cell = avgRow.GetCell(i);
- if (cell != null)
- {
- cell.CellStyle = avgStyle;
- }
+ sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, currentSampleCount));
}
}
@@ -751,31 +773,45 @@ namespace WindowsFormsApp6
{
int rowIndex = 3;
- // 时间行
- IRow timeRow = sheet.CreateRow(rowIndex++);
- timeRow.CreateCell(0).SetCellValue(TIME_ROW_LABEL);
- timeRow.GetCell(0).CellStyle = dataStyle;
+ // 从数据表中获取时间行数据
+ var timeRows = sampleDataTable.AsEnumerable()
+ .Where(r => r.Field("序号") == TIME_ROW_LABEL);
- for (int i = 1; i <= currentSampleCount; i++)
+ if (timeRows.Any())
{
- double value = 29 + i; // 示例数据
- ICell cell = timeRow.CreateCell(i);
- cell.SetCellValue(value);
- cell.CellStyle = yellowStyle;
- }
+ foreach (var dataRow in timeRows)
+ {
+ IRow timeRow = sheet.CreateRow(rowIndex++);
+ ICell labelCell = timeRow.CreateCell(0);
+ labelCell.SetCellValue(TIME_ROW_LABEL);
+ labelCell.CellStyle = dataStyle;
- // 不再添加"根据标准"列
+ for (int i = 1; i <= currentSampleCount; i++)
+ {
+ ICell cell = timeRow.CreateCell(i);
+ cell.SetCellValue(dataRow.Field($"试样{i}"));
+ cell.CellStyle = yellowStyle;
+ }
+ }
+ }
// 平均时间行
IRow avgRow = sheet.CreateRow(rowIndex);
- avgRow.CreateCell(0).SetCellValue(AVG_ROW_LABEL);
- avgRow.GetCell(0).CellStyle = dataStyle;
+ ICell avgLabelCell = avgRow.CreateCell(0);
+ avgLabelCell.SetCellValue(AVG_ROW_LABEL);
+ avgLabelCell.CellStyle = dataStyle;
+ // 计算并显示总平均值
+ double overallAvg = CalculateOverallAverage();
ICell avgCell = avgRow.CreateCell(1);
- avgCell.SetCellValue("32");
+ avgCell.SetCellValue(overallAvg);
avgCell.CellStyle = yellowStyle;
- sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, currentSampleCount));
+ // 合并所有试样列
+ if (currentSampleCount > 1)
+ {
+ sheet.AddMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, currentSampleCount));
+ }
}
///
diff --git a/WindowsFormsApp6/Form2.cs b/WindowsFormsApp6/Form2.cs
index e8082e0..06c8aa4 100644
--- a/WindowsFormsApp6/Form2.cs
+++ b/WindowsFormsApp6/Form2.cs
@@ -29,8 +29,12 @@ namespace WindowsFormsApp6
private const string ROW_INITIAL_WEIGHT = "初始重量(g)";
private const string ROW_AFTER_WEIGHT = "浸润后重量(g)";
private const string ROW_ABSORPTION = "液体吸收量(%)";
+ private const string ROW_SOAK_TIME = "浸润时间";
+ private const string ROW_HANG_TIME = "悬挂时间";
+ private const string ROW_RUN_SPEED = "运行速度";
private const string ROW_AVG_ABSORPTION = "液体吸收量平均值(%)";
private const string ROW_MAX_ABSORPTION = "液体吸收量最大值(%)";
+ private const string ROW_STD_DEVIATION = "标准偏差";
#endregion
#region 字段
@@ -297,8 +301,12 @@ namespace WindowsFormsApp6
{
var rowsToRemove = sampleDataTable.AsEnumerable()
.Where(r => r.Field("序号") == ROW_ABSORPTION ||
+ r.Field("序号") == ROW_SOAK_TIME ||
+ r.Field("序号") == ROW_HANG_TIME ||
+ r.Field("序号") == ROW_RUN_SPEED ||
r.Field("序号") == ROW_AVG_ABSORPTION ||
- r.Field("序号") == ROW_MAX_ABSORPTION)
+ r.Field("序号") == ROW_MAX_ABSORPTION ||
+ r.Field("序号") == ROW_STD_DEVIATION)
.ToList();
foreach (var row in rowsToRemove)
@@ -316,7 +324,7 @@ namespace WindowsFormsApp6
}
///
- /// 生成模拟测试数据
+ /// 生成模拟测试数据(精确模拟真实测试场景)
///
public void GenerateMockData()
{
@@ -327,16 +335,45 @@ namespace WindowsFormsApp6
double[] initialWeights = new double[currentSampleCount];
double[] afterWeights = new double[currentSampleCount];
+ // 设置基准值,使数据更真实
+ double baseInitialWeight = 15.0; // 基准初始重量
+ double baseAbsorptionRate = 0.35; // 基准吸收率 35%
+
for (int i = 0; i < currentSampleCount; i++)
{
- initialWeights[i] = Math.Round(MIN_WEIGHT + random.NextDouble() * (MAX_WEIGHT - MIN_WEIGHT), 2);
- afterWeights[i] = Math.Round(initialWeights[i] * (1.2 + random.NextDouble() * 0.3), 2); // 浸润后增重20%-50%
+ // 初始重量:在基准值附近波动 ±3g
+ initialWeights[i] = Math.Round(baseInitialWeight + (random.NextDouble() - 0.5) * 6.0, 2);
+
+ // 吸收率:在基准吸收率附近波动 ±10%
+ double absorptionRate = baseAbsorptionRate + (random.NextDouble() - 0.5) * 0.2;
+
+ // 浸润后重量 = 初始重量 × (1 + 吸收率)
+ afterWeights[i] = Math.Round(initialWeights[i] * (1 + absorptionRate), 2);
}
sampleCount = 1;
UpdateDisplay(initialWeights, afterWeights);
- ShowMessage($"已生成 {currentSampleCount} 个试样的模拟数据", "模拟数据生成");
+ // 计算并显示统计信息
+ double[] absorptions = new double[currentSampleCount];
+ for (int i = 0; i < currentSampleCount; i++)
+ {
+ absorptions[i] = ((afterWeights[i] - initialWeights[i]) / initialWeights[i]) * 100;
+ }
+
+ double avgAbsorption = absorptions.Average();
+ double stdDev = CalculateStandardDeviation(absorptions);
+ double maxAbsorption = absorptions.Max();
+ double minAbsorption = absorptions.Min();
+
+ string message = $"已生成 {currentSampleCount} 个试样的模拟数据\n\n" +
+ $"液体吸收量统计:\n" +
+ $"平均值:{avgAbsorption:F2}%\n" +
+ $"标准偏差:{stdDev:F2}%\n" +
+ $"最大值:{maxAbsorption:F2}%\n" +
+ $"最小值:{minAbsorption:F2}%";
+
+ ShowMessage(message, "模拟数据生成");
}
///
@@ -377,29 +414,57 @@ namespace WindowsFormsApp6
}
sampleDataTable.Rows.Add(absorptionRow);
- // 4. 液体吸收量平均值行
+ // 4. 浸润时间行
+ DataRow soakTimeRow = sampleDataTable.NewRow();
+ soakTimeRow["序号"] = ROW_SOAK_TIME;
+ // 为每个试样生成浸润时间(基准60s,波动±10s)
+ for (int i = 1; i <= count; i++)
+ {
+ int soakTime = 60 + random.Next(-10, 11); // 50-70秒
+ soakTimeRow[$"试样{i}"] = $"{soakTime}s";
+ }
+ sampleDataTable.Rows.Add(soakTimeRow);
+
+ // 5. 悬挂时间行
+ DataRow hangTimeRow = sampleDataTable.NewRow();
+ hangTimeRow["序号"] = ROW_HANG_TIME;
+ // 为每个试样生成悬挂时间(基准30s,波动±5s)
+ for (int i = 1; i <= count; i++)
+ {
+ int hangTime = 30 + random.Next(-5, 6); // 25-35秒
+ hangTimeRow[$"试样{i}"] = $"{hangTime}s";
+ }
+ sampleDataTable.Rows.Add(hangTimeRow);
+
+ // 6. 运行速度行
+ DataRow runSpeedRow = sampleDataTable.NewRow();
+ runSpeedRow["序号"] = ROW_RUN_SPEED;
+ // 为每个试样生成运行速度(基准100mm/min,波动±10mm/min)
+ for (int i = 1; i <= count; i++)
+ {
+ int runSpeed = 100 + random.Next(-10, 11); // 90-110 mm/min
+ runSpeedRow[$"试样{i}"] = $"{runSpeed}mm/min";
+ }
+ sampleDataTable.Rows.Add(runSpeedRow);
+
+ // 7. 液体吸收量平均值行
DataRow avgRow = sampleDataTable.NewRow();
avgRow["序号"] = ROW_AVG_ABSORPTION;
- double avgAbsorption = absorptions.Average();
- double stdDev = CalculateStandardDeviation(absorptions);
+
+ // 根据实际试样数量计算平均值
+ double avgAbsorption = count > 0 ? absorptions.Take(count).Average() : 0;
// 第1列显示平均值
avgRow["试样1"] = avgAbsorption;
- // 第2列显示标准偏差
- if (count >= 2)
- {
- avgRow["试样2"] = stdDev;
- }
-
// 其他列为空
- for (int i = 3; i <= count; i++)
+ for (int i = 2; i <= count; i++)
{
avgRow[$"试样{i}"] = DBNull.Value;
}
sampleDataTable.Rows.Add(avgRow);
- // 5. 液体吸收量最大值行
+ // 8. 液体吸收量最大值行
DataRow maxRow = sampleDataTable.NewRow();
maxRow["序号"] = ROW_MAX_ABSORPTION;
double maxAbsorption = absorptions.Max();
@@ -414,20 +479,38 @@ namespace WindowsFormsApp6
}
sampleDataTable.Rows.Add(maxRow);
+ // 9. 标准偏差行(最后一行)
+ DataRow stdDevRow = sampleDataTable.NewRow();
+ stdDevRow["序号"] = ROW_STD_DEVIATION;
+
+ // 根据实际试样数量计算标准偏差
+ double stdDev = count > 1 ? CalculateStandardDeviation(absorptions.Take(count).ToArray()) : 0;
+
+ // 第1列显示标准偏差
+ stdDevRow["试样1"] = stdDev;
+
+ // 其他列为空
+ for (int i = 2; i <= count; i++)
+ {
+ stdDevRow[$"试样{i}"] = DBNull.Value;
+ }
+ sampleDataTable.Rows.Add(stdDevRow);
+
// 刷新界面
RefreshDataGridView();
}
///
- /// 计算标准偏差
+ /// 计算标准偏差(样本标准偏差,n-1)
///
private double CalculateStandardDeviation(double[] values)
{
- if (values.Length == 0) return 0;
+ if (values == null || values.Length <= 1) return 0;
double avg = values.Average();
double sumOfSquares = values.Sum(val => Math.Pow(val - avg, 2));
- return Math.Sqrt(sumOfSquares / values.Length);
+ // 使用样本标准偏差公式:除以 (n-1)
+ return Math.Sqrt(sumOfSquares / (values.Length - 1));
}
///
diff --git a/WindowsFormsApp6/Form3.cs b/WindowsFormsApp6/Form3.cs
index 9a23828..c39c095 100644
--- a/WindowsFormsApp6/Form3.cs
+++ b/WindowsFormsApp6/Form3.cs
@@ -862,75 +862,74 @@ namespace WindowsFormsApp6
///
/// 计算平均芯吸速率(mm/min)
+ /// 计算方式:每组试样显示该组3次测试的平均值
///
private void CalculateAverageWickingRate()
{
- List rates = new List();
-
if (isVerticalLayout)
{
// 纵向布局
DataRow rateRow = sampleDataTable.Rows[2];
DataRow avgRow = sampleDataTable.Rows[3];
+ // 计算每组试样的平均值,并填充到对应列
for (int i = 1; i <= currentSampleCount; i++)
{
double rate1 = ConvertToDouble(rateRow[$"试样{i}_1"]);
double rate2 = ConvertToDouble(rateRow[$"试样{i}_2"]);
double rate3 = ConvertToDouble(rateRow[$"试样{i}_3"]);
- if (rate1 > 0) rates.Add(rate1);
- if (rate2 > 0) rates.Add(rate2);
- if (rate3 > 0) rates.Add(rate3);
- }
-
- double average = rates.Count > 0 ? rates.Average() : 0;
-
- for (int i = 1; i <= currentSampleCount; i++)
- {
- avgRow[$"试样{i}_3"] = Math.Round(average, 2);
+ List groupRates = new List();
+ if (rate1 > 0) groupRates.Add(rate1);
+ if (rate2 > 0) groupRates.Add(rate2);
+ if (rate3 > 0) groupRates.Add(rate3);
+
+ // 计算该组平均值
+ double groupAvg = groupRates.Count > 0 ? groupRates.Average() : 0;
+
+ // 填充到该试样的第3列
+ avgRow[$"试样{i}_3"] = Math.Round(groupAvg, 2);
}
}
else
{
// 横向布局
- foreach (DataRow row in sampleDataTable.Rows)
- {
- double rate = ConvertToDouble(row[ROW_WICKING_RATE]);
- if (rate > 0) rates.Add(rate);
- }
-
- double average = rates.Count > 0 ? rates.Average() : 0;
-
- // 只在每个试样的第3次测试显示平均值
- int rowIndex = 0;
+ // 计算每组试样的平均值
for (int i = 1; i <= currentSampleCount; i++)
{
+ List groupRates = new List();
+
for (int j = 1; j <= 3; j++)
{
+ int rowIndex = (i - 1) * 3 + (j - 1);
if (rowIndex < sampleDataTable.Rows.Count)
{
- if (j == 3)
- {
- sampleDataTable.Rows[rowIndex][ROW_AVG_WICKING_RATE] = Math.Round(average, 2);
- }
- else
- {
- sampleDataTable.Rows[rowIndex][ROW_AVG_WICKING_RATE] = 0.0;
- }
- rowIndex++;
+ double rate = ConvertToDouble(sampleDataTable.Rows[rowIndex][ROW_WICKING_RATE]);
+ if (rate > 0) groupRates.Add(rate);
}
}
+
+ // 计算该组平均值
+ double groupAvg = groupRates.Count > 0 ? groupRates.Average() : 0;
+
+ // 填充到该组的第3次测试行
+ int targetRowIndex = (i - 1) * 3 + 2; // 第3次测试的行索引
+ if (targetRowIndex < sampleDataTable.Rows.Count)
+ {
+ sampleDataTable.Rows[targetRowIndex][ROW_AVG_WICKING_RATE] = Math.Round(groupAvg, 2);
+ }
}
}
}
///
/// 计算标准偏差
+ /// 计算方式:基于每组试样的平均芯吸速率计算标准偏差(组间标准偏差)
+ /// 结果:只有一个标准偏差值,合并显示在第1列
///
private void CalculateStandardDeviation()
{
- List rates = new List();
+ List groupAverages = new List(); // 存储每组的平均值
if (isVerticalLayout)
{
@@ -938,64 +937,102 @@ namespace WindowsFormsApp6
DataRow rateRow = sampleDataTable.Rows[2];
DataRow stdRow = sampleDataTable.Rows[4];
+ // 计算每组试样的平均值
for (int i = 1; i <= currentSampleCount; i++)
{
double rate1 = ConvertToDouble(rateRow[$"试样{i}_1"]);
double rate2 = ConvertToDouble(rateRow[$"试样{i}_2"]);
double rate3 = ConvertToDouble(rateRow[$"试样{i}_3"]);
- if (rate1 > 0) rates.Add(rate1);
- if (rate2 > 0) rates.Add(rate2);
- if (rate3 > 0) rates.Add(rate3);
+ List groupRates = new List();
+ if (rate1 > 0) groupRates.Add(rate1);
+ if (rate2 > 0) groupRates.Add(rate2);
+ if (rate3 > 0) groupRates.Add(rate3);
+
+ // 如果该组有有效数据,计算该组平均值
+ if (groupRates.Count > 0)
+ {
+ double groupAvg = groupRates.Average();
+ groupAverages.Add(groupAvg);
+ }
}
+ // 基于组平均值计算标准偏差
double stdDev = 0;
- if (rates.Count > 1)
+ if (groupAverages.Count > 1)
{
- double average = rates.Average();
- double sumOfSquares = rates.Sum(r => Math.Pow(r - average, 2));
- stdDev = Math.Sqrt(sumOfSquares / (rates.Count - 1));
+ double overallAverage = groupAverages.Average();
+ double sumOfSquares = groupAverages.Sum(avg => Math.Pow(avg - overallAverage, 2));
+ stdDev = Math.Sqrt(sumOfSquares / (groupAverages.Count - 1));
}
+ // 只在第1列显示标准偏差,其他列清空
for (int i = 1; i <= currentSampleCount; i++)
{
- stdRow[$"试样{i}_3"] = Math.Round(stdDev, 2);
+ if (i == 1)
+ {
+ stdRow[$"试样{i}_1"] = Math.Round(stdDev, 2);
+ }
+ else
+ {
+ stdRow[$"试样{i}_1"] = 0.0;
+ stdRow[$"试样{i}_2"] = 0.0;
+ stdRow[$"试样{i}_3"] = 0.0;
+ }
}
}
else
{
// 横向布局
- foreach (DataRow row in sampleDataTable.Rows)
+ // 计算每组试样的平均值
+ for (int i = 1; i <= currentSampleCount; i++)
{
- double rate = ConvertToDouble(row[ROW_WICKING_RATE]);
- if (rate > 0) rates.Add(rate);
+ List groupRates = new List();
+
+ for (int j = 1; j <= 3; j++)
+ {
+ int rowIndex = (i - 1) * 3 + (j - 1);
+ if (rowIndex < sampleDataTable.Rows.Count)
+ {
+ double rate = ConvertToDouble(sampleDataTable.Rows[rowIndex][ROW_WICKING_RATE]);
+ if (rate > 0) groupRates.Add(rate);
+ }
+ }
+
+ // 如果该组有有效数据,计算该组平均值
+ if (groupRates.Count > 0)
+ {
+ double groupAvg = groupRates.Average();
+ groupAverages.Add(groupAvg);
+ }
}
+ // 基于组平均值计算标准偏差
double stdDev = 0;
- if (rates.Count > 1)
+ if (groupAverages.Count > 1)
{
- double average = rates.Average();
- double sumOfSquares = rates.Sum(r => Math.Pow(r - average, 2));
- stdDev = Math.Sqrt(sumOfSquares / (rates.Count - 1));
+ double overallAverage = groupAverages.Average();
+ double sumOfSquares = groupAverages.Sum(avg => Math.Pow(avg - overallAverage, 2));
+ stdDev = Math.Sqrt(sumOfSquares / (groupAverages.Count - 1));
}
- // 只在每个试样的第3次测试显示标准偏差
- int rowIndex = 0;
+ // 只在第1行显示标准偏差,其他行清空
+ int dataRowIndex = 0;
for (int i = 1; i <= currentSampleCount; i++)
{
for (int j = 1; j <= 3; j++)
{
- if (rowIndex < sampleDataTable.Rows.Count)
+ if (dataRowIndex < sampleDataTable.Rows.Count)
{
- if (j == 3)
+ if (dataRowIndex == 0) // 只在第1行显示
{
- sampleDataTable.Rows[rowIndex][ROW_STD_DEVIATION] = Math.Round(stdDev, 2);
+ sampleDataTable.Rows[dataRowIndex][ROW_STD_DEVIATION] = Math.Round(stdDev, 2);
}
else
{
- sampleDataTable.Rows[rowIndex][ROW_STD_DEVIATION] = 0.0;
+ sampleDataTable.Rows[dataRowIndex][ROW_STD_DEVIATION] = 0.0;
}
- rowIndex++;
+ dataRowIndex++;
}
}
}