为所有大物1的py配置ipynb,但是均未经过测试

This commit is contained in:
SOR
2026-09-22 16:04:12 +08:00
parent af6d2bbc93
commit 664c80166b
24 changed files with 1893 additions and 3 deletions
+187
View File
@@ -0,0 +1,187 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 电桥法测量电阻计算器 (Wheatstone Bridge)\n",
"\n",
"本 Notebook 用于通过**惠斯通电桥(单臂电桥)**测量未知电阻值 $R_x$。包含不同比例臂($1:1, 1:10, 10:1$ 等)下的平衡电阻统计、电桥灵敏度 $S$ 测定、仪器误差限 $\\Delta_{\\mathrm{inst}}$ 评估、不确定度合成及各比例臂对比汇总。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 惠斯通电桥平衡条件\n",
"当检流计指针示数为零时,电桥达到平衡:\n",
"$$R_x = R_0 \\cdot \\frac{R_1}{R_2} = R_0 \\cdot C$$\n",
"* $R_x$:待测电阻\n",
"* $R_0$:比较臂标准电阻箱读数\n",
"* $C = R_1 / R_2$:比例臂倍率(如 $1, 0.1, 10$)\n",
"\n",
"#### 2. 电桥灵敏度 $S$ 与仪器误差限 $\\Delta_{\\mathrm{inst}}$\n",
"平衡后微调比较臂电阻使检流计偏转 $\\Delta n$ 格(通常取 5 格),记偏调后的读数为 $R_0'$:\n",
"$$\\Delta R_0 = |R_0' - R_0|, \\quad S = \\frac{\\Delta n}{\\Delta R_0 / R_0} = \\frac{\\Delta n \\cdot R_0}{\\Delta R_0}$$\n",
"电桥所能分辨的最小电阻改变量(即由灵敏度决定的仪器误差限)为:\n",
"$$\\Delta_{\\mathrm{inst}} = \\frac{R_0}{S} = \\frac{\\Delta R_0}{\\Delta n}$$\n",
"\n",
"#### 3. 不确定度传递与合成公式\n",
"比例臂 $C$ 由精密标准电阻构成,其不确定度可忽略,则:\n",
"* $R_0$ 的合成不确定度:\n",
"$$u(R_0) = \\sqrt{ u_A^2(R_0) + u_B^2(R_0) }, \\quad u_A(R_0) = \\frac{s(R_0)}{\\sqrt{n}}, \\quad u_B(R_0) = \\frac{\\Delta_{\\mathrm{inst}}}{\\sqrt{3}}$$\n",
"* 待测电阻 $R_x$ 的不确定度:\n",
"$$u(R_x) = C \\cdot u(R_0), \\quad u_r(R_x) = \\frac{u(R_x)}{R_x} = \\frac{u(R_0)}{R_0}$$\n",
"* 结果按照“四舍六入五凑偶”保留一位有效数字,末位对齐。"
],
"id": "aae827c35ef68a9f"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"from decimal import Decimal\n",
"from python.utils import scientific_round, calculate_stats\n",
"\n",
"print(\"电桥法计算模块加载完成。\")"
],
"id": "c7d75a2788fc0cac"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 测量实验数据配置 (支持多组标称值与比例臂)\n",
"> **提示**:可以在 `calibration_data` 列表中增减测试组。每组包含:标称值、比例臂标签、比例因子 $C$、5次平衡读数 $R_0$ 列表,以及偏转 5 格时的读数 $R_0'$。"
],
"id": "44f6b780972c58ad"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 实验测量数据配置列表\n",
"# 结构: dict(R_nominal, ratio_label, C, R0_list, R0_prime)\n",
"calibration_data = [\n",
" {\n",
" \"R_nominal\": \"10000\", \"ratio_label\": \"1:1\", \"C\": Decimal(\"1\"),\n",
" \"R0_list\": [Decimal(\"9985.2\"), Decimal(\"9985.0\"), Decimal(\"9985.3\"), Decimal(\"9985.1\"), Decimal(\"9985.2\")],\n",
" \"R0_prime\": Decimal(\"9995.2\")\n",
" },\n",
" {\n",
" \"R_nominal\": \"10000\", \"ratio_label\": \"10:1\", \"C\": Decimal(\"10\"),\n",
" \"R0_list\": [Decimal(\"998.5\"), Decimal(\"998.4\"), Decimal(\"998.6\"), Decimal(\"998.5\"), Decimal(\"998.5\")],\n",
" \"R0_prime\": Decimal(\"1002.5\")\n",
" },\n",
" {\n",
" \"R_nominal\": \"2000\", \"ratio_label\": \"1:1\", \"C\": Decimal(\"1\"),\n",
" \"R0_list\": [Decimal(\"1996.8\"), Decimal(\"1996.9\"), Decimal(\"1996.7\"), Decimal(\"1996.8\"), Decimal(\"1996.8\")],\n",
" \"R0_prime\": Decimal(\"2002.8\")\n",
" },\n",
" {\n",
" \"R_nominal\": \"2000\", \"ratio_label\": \"10:1\", \"C\": Decimal(\"10\"),\n",
" \"R0_list\": [Decimal(\"199.7\"), Decimal(\"199.6\"), Decimal(\"199.7\"), Decimal(\"199.8\"), Decimal(\"199.7\")],\n",
" \"R0_prime\": Decimal(\"201.2\")\n",
" },\n",
" {\n",
" \"R_nominal\": \"200\", \"ratio_label\": \"1:1\", \"C\": Decimal(\"1\"),\n",
" \"R0_list\": [Decimal(\"199.65\"), Decimal(\"199.62\"), Decimal(\"199.68\"), Decimal(\"199.64\"), Decimal(\"199.65\")],\n",
" \"R0_prime\": Decimal(\"201.15\")\n",
" },\n",
" {\n",
" \"R_nominal\": \"200\", \"ratio_label\": \"1:10\", \"C\": Decimal(\"0.1\"),\n",
" \"R0_list\": [Decimal(\"1996.4\"), Decimal(\"1996.2\"), Decimal(\"1996.5\"), Decimal(\"1996.4\"), Decimal(\"1996.3\")],\n",
" \"R0_prime\": Decimal(\"2005.4\")\n",
" },\n",
" {\n",
" \"R_nominal\": \"200\", \"ratio_label\": \"10:1\", \"C\": Decimal(\"10\"),\n",
" \"R0_list\": [Decimal(\"19.96\"), Decimal(\"19.95\"), Decimal(\"19.97\"), Decimal(\"19.96\"), Decimal(\"19.96\")],\n",
" \"R0_prime\": Decimal(\"20.36\")\n",
" }\n",
"]\n",
"\n",
"print(f\"成功载入 {len(calibration_data)} 组电桥测量方案。\")"
],
"id": "c3bfc04680149d32"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 批量计算、灵敏度分析与不确定度评定"
],
"id": "254400fffad68f9"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"delta_n = Decimal(\"5\") # 偏转格数\n",
"results = []\n",
"\n",
"for item in calibration_data:\n",
" R_nom = item[\"R_nominal\"]\n",
" ratio = item[\"ratio_label\"]\n",
" C = item[\"C\"]\n",
" R0_data = item[\"R0_list\"]\n",
" R0_prime = item[\"R0_prime\"]\n",
" \n",
" R0_mean_temp = sum(R0_data) / Decimal(len(R0_data))\n",
" delta_R0 = abs(R0_prime - R0_mean_temp)\n",
" \n",
" if delta_R0 == 0:\n",
" S = Decimal(\"Infinity\")\n",
" delta_inst = Decimal(\"0\")\n",
" else:\n",
" S = delta_n * R0_mean_temp / delta_R0\n",
" delta_inst = R0_mean_temp / S\n",
" \n",
" R0_mean, u_R0, u_a_R0, u_b_R0, _ = calculate_stats(R0_data, str(delta_inst))\n",
" \n",
" Rx_mean = C * R0_mean\n",
" u_Rx = C * u_R0\n",
" u_r_Rx = u_Rx / Rx_mean if Rx_mean != 0 else Decimal(\"0\")\n",
" Rx_final, u_Rx_final = scientific_round(Rx_mean, u_Rx)\n",
" \n",
" results.append({\n",
" \"R_nominal\": R_nom, \"ratio_label\": ratio, \"C\": C,\n",
" \"R0_mean\": R0_mean, \"S\": S, \"delta_inst\": delta_inst,\n",
" \"Rx_mean\": Rx_mean, \"u_Rx\": u_Rx, \"u_r_Rx\": u_r_Rx,\n",
" \"Rx_final\": Rx_final, \"u_Rx_final\": u_Rx_final\n",
" })\n",
"\n",
"print(\"=\" * 85)\n",
"print(\" 测 量 结 果 汇 总 表 \")\n",
"print(\"=\" * 85)\n",
"header = f\"{'标定电阻':>8} {'比例臂':>8} {'R0均值(Ω)':>12} {'灵敏度S':>10} {'Δ_inst(Ω)':>12} {'Rx(Ω)':>12} {'u(Rx)(Ω)':>10} {'相对不确定度':>10}\"\n",
"print(header)\n",
"print(\"-\" * 85)\n",
"for res in results:\n",
" S_str = f\"{res['S']:.1f}\" if res['S'] != Decimal(\"Infinity\") else \"∞\"\n",
" print(f\"{res['R_nominal'] + ' Ω':>8} {res['ratio_label']:>8} {res['R0_mean']:>12.4f} {S_str:>10} \"\n",
" f\"{res['delta_inst']:>12.4f} {res['Rx_mean']:>12.4f} {res['u_Rx']:>10.4f} {res['u_r_Rx']*100:>9.2f}%\")\n",
"print(\"=\" * 85)\n",
"\n",
"print(\"\\n\" + \"*\" * 55)\n",
"print(\" 最 终 规 范 修 约 结 果 \")\n",
"print(\"*\" * 55)\n",
"for res in results:\n",
" print(f\"标定 {res['R_nominal']:>5} Ω (比例臂 {res['ratio_label']:>4}) : Rx = {res['Rx_final']} ± {res['u_Rx_final']} Ω\")\n",
"print(\"*\" * 55)"
],
"id": "9a88f538183e4b0c"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+311
View File
@@ -0,0 +1,311 @@
import math
from decimal import Decimal
from utils import (
scientific_round,
calculate_stats,
input_decimal,
input_int
)
"""
Wheatstone Bridge Resistance Measurement Calculator
电桥法测量电阻计算器
参考了表面张力系数计算器的高精度与不确定度修约逻辑。
公式说明:
1. 惠斯通电桥平衡条件 (Bridge Balance Equation):
当检流计示数为零时,电桥平衡:
Rx / R0 = R1 / R2
即:
Rx = R0 * (R1 / R2) (也写作 Rx = R0 * C,C = R1/R2 为比例臂比值)
其中:
Rx : 待测电阻
R0 : 比较臂标准电阻(电桥读数)
R1/R2 : 比例臂之比,取 1:1, 1:10, 10:1
2. 灵敏度公式 (Bridge Sensitivity):
S = Δn / (ΔR0 / R0)
其中:
S : 电桥灵敏度(格/相对变化量)
Δn : 检流计偏转格数(通常取 5 小格)
ΔR0 : 使检流计偏转 Δn 格时 R0 的改变量
ΔR0 = |R0' - R0|,R0' 为偏转 5 格时的读数
R0 : 平衡时的标准电阻读数
也可写为:
S = Δn * R0 / ΔR0
3. 不确定度传递公式 (Uncertainty Propagation):
Rx = R0 * C (C 为比例臂比值)
(a) R0 的不确定度:
u(R0) = sqrt( u_A(R0)^2 + u_B(R0)^2 )
其中:
u_A(R0) = s(R0) / sqrt(n) (A 类不确定度, s 为标准偏差)
u_B(R0) = Δ_inst / sqrt(3) (B 类不确定度, Δ_inst 为仪器误差限)
(b) 仪器误差限 Δ_inst 的确定 (与灵敏度有关):
Δ_inst = R0 / S
即由灵敏度决定的电桥最小可分辨电阻变化量
(c) 比例臂 C 视为精确值(标准电阻箱),则:
u(Rx) = C * u(R0)
(d) 相对不确定度:
u_r(Rx) = u(Rx) / Rx = u(R0) / R0
(e) 修约规则:
不确定度保留一位有效数字,四舍六入五凑偶
Rx 末位与不确定度对齐
"""
def measure_one_ratio(ratio_label, C_value, R_nominal, n_measurements):
"""
对单一比例臂进行测量与分析
参数:
ratio_label: 比例臂标签,如 "1:1"
C_value: 比例臂比值 C = R1/R2
R_nominal: 标定电阻标称值 (Ω)
n_measurements: 测量次数
"""
C = Decimal(str(C_value))
print(f"\n{'─'*50}")
print(f" 比例臂 Rx:R0 = {ratio_label},比例因子 C = {C_value}")
print(f" 标定电阻标称值: {R_nominal} Ω")
print(f"{'─'*50}")
# --- 输入平衡时的 R0 读数 ---
print(f"\n请输入 {n_measurements} 次平衡时的 R0 读数 (Ω):")
R0_data = []
for i in range(n_measurements):
while True:
try:
val = input(f" 第 {i+1} 次 R0 = ").strip()
if not val: continue
R0_data.append(Decimal(val))
break
except Exception:
print(" 输入无效,请输入数字。")
# --- 输入偏差 5 小格时的 R0' ---
print(f"\n请输入偏转 5 小格时的 R0' 读数 (Ω):")
R0_prime = input_decimal(" R0'")
delta_n = Decimal("5") # 检流计偏转格数
# --- 计算 R0 的平均值 ---
R0_mean = sum(R0_data) / Decimal(len(R0_data))
# --- 计算灵敏度 ---
# S = Δn * R0 / |R0' - R0|
delta_R0 = abs(R0_prime - R0_mean)
if delta_R0 == 0:
print(" ⚠ 警告: R0' = R0,无法计算灵敏度,请检查数据!")
S = Decimal("Infinity")
delta_inst = Decimal("0")
else:
S = delta_n * R0_mean / delta_R0
# 仪器误差限 (由灵敏度决定)
# Δ_inst = R0 / S = |R0' - R0| / Δn = ΔR0 / 5
delta_inst = R0_mean / S
# --- 不确定度分析 ---
R0_mean_final, u_R0, u_a_R0, u_b_R0, _ = calculate_stats(R0_data, str(delta_inst))
# Rx = C * R0
Rx_mean = C * R0_mean_final
u_Rx = C * u_R0
# 相对不确定度
if Rx_mean != 0:
u_r_Rx = u_Rx / Rx_mean
else:
u_r_Rx = Decimal("0")
# --- 修约 ---
Rx_final, u_Rx_final = scientific_round(Rx_mean, u_Rx)
# --- 输出结果 ---
print(f"\n{'═'*50}")
print(f" 结果 (比例臂 {ratio_label}, 标定 {R_nominal} Ω)")
print(f"{'═'*50}")
# 打印 R0 测量数据表
print(f"\n R0 测量数据:")
for i, val in enumerate(R0_data):
print(f" 第 {i+1} 次: {val} Ω")
print(f"\n R0 平均值 = {R0_mean_final:.4f} Ω")
print(f" R0' = {R0_prime} Ω")
print(f" ΔR0 = |R0'-R0| = {delta_R0:.4f} Ω")
print(f" 偏转格数 Δn = {delta_n} 格")
print(f"{'─'*50}")
print(f" 灵敏度 S = Δn·R0/ΔR0 = {S:.2f}")
print(f" 仪器误差限 Δ_inst = R0/S = {delta_inst:.4f} Ω")
print(f"{'─'*50}")
print(f" u_A(R0) = {u_a_R0:.6f} Ω")
print(f" u_B(R0) = {u_b_R0:.6f} Ω")
print(f" u(R0) = {u_R0:.6f} Ω")
print(f"{'─'*50}")
print(f" Rx = C × R0 = {C} × {R0_mean_final:.4f} = {Rx_mean:.4f} Ω")
print(f" u(Rx) = C × u(R0) = {u_Rx:.6f} Ω")
print(f" 相对不确定度 u_r = {u_r_Rx*100:.2f}%")
print(f"{'─'*50}")
print(f" ★ 最终结果: Rx = {Rx_final} ± {u_Rx_final} Ω")
print(f"{'═'*50}")
return {
"ratio_label": ratio_label,
"C": C,
"R_nominal": R_nominal,
"R0_data": R0_data,
"R0_mean": R0_mean_final,
"R0_prime": R0_prime,
"delta_R0": delta_R0,
"S": S,
"delta_inst": delta_inst,
"u_a_R0": u_a_R0,
"u_b_R0": u_b_R0,
"u_R0": u_R0,
"Rx_mean": Rx_mean,
"u_Rx": u_Rx,
"u_r_Rx": u_r_Rx,
"Rx_final": Rx_final,
"u_Rx_final": u_Rx_final
}
def main():
print("════════════════════════════════════════════════")
print(" 电桥法测量电阻计算器 (Wheatstone Bridge)")
print("════════════════════════════════════════════════")
print()
print("实验原理:")
print(" 惠斯通电桥平衡条件: Rx = R0 × C (C = R1/R2)")
print(" 灵敏度: S = Δn × R0 / ΔR0")
print(" 不确定度: u(Rx) = C × u(R0), u(R0) = √(u_A² + u_B²)")
print()
# --- 1. 基本参数 ---
n_meas = input_int("每组测量次数 n", default=5)
# --- 2. 定义测量方案 ---
# 标定电阻: 10kΩ 和 2kΩ
# 比例臂: 1:1, 1:10, 10:1
# 注意: 2kΩ 不会有 1:10 的比例臂 (因为 R0 = Rx/(C) 会超出电阻箱量程)
calibration_plan = [
# (标定电阻标称值, 比例臂标签, C 值)
# ---- 10kΩ 标定 ----
("10000", "1:1", 1),
("10000", "10:1", 10),
# ---- 2kΩ 标定 ----
("2000", "1:1", 1),
("2000", "10:1", 10),
# ---- 200Ω 标定 ----
("200", "1:1", 1),
("200", "1:10", 0.1),
("200", "10:1", 10),
]
print(f"\n{'━'*55}")
print(" 测量方案如下:")
print(f"{'━'*55}")
print(f" {'序号':<6}{'标定电阻':>10}{'比例臂 Rx:R0':>14}{'C = R1/R2':>12}")
print(f" {'─'*46}")
for idx, (R_nom, ratio, C_val) in enumerate(calibration_plan, 1):
print(f" {idx:<6}{R_nom + ' Ω':>10}{ratio:>14}{C_val:>12}")
print(f"{'━'*55}")
print()
print(" 注: 2kΩ 标定不进行 1:10 比例臂测量")
print(" (R0 = 2000/0.1 = 20000 Ω,超出电阻箱量程)")
print()
# --- 3. 逐项测量 ---
all_results = []
for idx, (R_nom, ratio_label, C_val) in enumerate(calibration_plan, 1):
print(f"\n{'▓'*55}")
print(f" 第 {idx} 组: 标定 {R_nom} Ω,比例臂 Rx:R0 = {ratio_label}")
print(f"{'▓'*55}")
result = measure_one_ratio(ratio_label, C_val, R_nom, n_meas)
all_results.append(result)
if idx < len(calibration_plan):
input("\n按回车继续下一组测量...")
# --- 4. 汇总表 ---
print("\n")
print("╔══════════════════════════════════════════════════════════════════════════════╗")
print("║ 测 量 结 果 汇 总 表 ║")
print("╠══════════════════════════════════════════════════════════════════════════════╣")
header = (f" {'标定':>6} {'比例臂':>8} {'R0均值(Ω)':>12} "
f"{'S(灵敏度)':>10} {'Δ_inst(Ω)':>10} "
f"{'Rx(Ω)':>12} {'u(Rx)(Ω)':>10} {'u_r(%)':>8}")
print(header)
print(f" {'─'*74}")
for res in all_results:
S_str = f"{res['S']:.1f}" if res['S'] != Decimal("Infinity") else "∞"
line = (f" {res['R_nominal']:>6} {res['ratio_label']:>8} "
f"{res['R0_mean']:>12.4f} {S_str:>10} "
f"{res['delta_inst']:>10.4f} "
f"{res['Rx_mean']:>12.4f} {res['u_Rx']:>10.6f} "
f"{res['u_r_Rx']*100:>7.2f}%")
print(line)
print("╚══════════════════════════════════════════════════════════════════════════════╝")
# --- 5. 灵敏度分析总结 ---
print("\n")
print("┌──────────────────────────────────────────────┐")
print("│ 灵 敏 度 分 析 总 结 │")
print("├──────────────────────────────────────────────┤")
for res in all_results:
S_str = f"{res['S']:.2f}" if res['S'] != Decimal("Infinity") else "∞"
print(f"│ 标定 {res['R_nominal']:>5}Ω 比例臂 {res['ratio_label']:>4} "
f"S = {S_str:>8} │")
print("├──────────────────────────────────────────────┤")
# 找灵敏度最大和最小
finite_results = [r for r in all_results if r['S'] != Decimal("Infinity")]
if finite_results:
best = max(finite_results, key=lambda r: r['S'])
worst = min(finite_results, key=lambda r: r['S'])
print(f"│ 最高灵敏度: 标定{best['R_nominal']:>5}Ω 比例臂{best['ratio_label']:>4} │")
print(f"│ S = {best['S']:.2f} │")
print(f"│ 最低灵敏度: 标定{worst['R_nominal']:>5}Ω 比例臂{worst['ratio_label']:>4} │")
print(f"│ S = {worst['S']:.2f} │")
print("├──────────────────────────────────────────────┤")
print("│ 分析: │")
print("│ · 灵敏度 S 越大,测量精度越高 │")
print("│ · S = Δn·R0/ΔR0 │")
print("│ · 比例臂比值影响灵敏度 │")
print("│ · 合理选择比例臂可优化测量精度 │")
print("└──────────────────────────────────────────────┘")
# --- 6. 最终修约结果汇总 ---
print("\n")
print("╔═══════════════════════════════════════════════════╗")
print("║ 最 终 结 果 (修约后) ║")
print("╠═══════════════════════════════════════════════════╣")
for res in all_results:
print(f"║ 标定 {res['R_nominal']:>5}Ω 比例臂 {res['ratio_label']:>4}: ║")
print(f"║ Rx = {res['Rx_final']} ± {res['u_Rx_final']} Ω ║")
print(f"║ (相对不确定度 {res['u_r_Rx']*100:.2f}%) ║")
print(f"╟───────────────────────────────────────────────────╢")
print("╚═══════════════════════════════════════════════════╝")
if __name__ == "__main__":
main()
+210
View File
@@ -0,0 +1,210 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 霍尔效应实验数据处理 (Hall Effect)\n",
"\n",
"本 Notebook 用于对霍尔效应实验中直接测得的霍尔电压 $V_H$ 及零磁场电导电压 $V_\\sigma$ 进行线性拟合、导电类型判别、物理参数计算(电导率 $\\sigma$、霍尔灵敏度 $K_H$、霍尔系数 $R_H$、载流子浓度 $n$ 与迁移率 $\\mu$)及完整的不确定度传递分析。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 霍尔效应基本关系与载流子类型判别\n",
"将通有控制工作电流 $I_s$ 的半导体薄片置于垂直磁场 $B$ 中,受洛伦兹力偏转产生横向霍尔电压 $V_H$:\n",
"$$V_H = K_H \\cdot I_s \\cdot B$$\n",
"* 若 $V_H > 0$:空穴导电,判定为 **P 型半导体**;\n",
"* 若 $V_H < 0$:电子导电,判定为 **N 型半导体**。\n",
"\n",
"#### 2. 磁场计算(螺线管)\n",
"励磁电流为 $I_m$,螺线管中心磁场强度满足:\n",
"$$B = k_{\\mathrm{sol}} \\cdot I_m = \\left(\\mu_0 \\frac{N}{L_{\\mathrm{sol}}}\\right) I_m$$\n",
"\n",
"#### 3. 电导率 $\\sigma$ 计算\n",
"在零磁场 ($I_m = 0$) 条件下测定不同工作电流 $I_s$ 下沿长度方向的电位差 $V_\\sigma$。线性回归斜率即为霍尔片电阻 $R = V_\\sigma / I_s$,则材料电导率为:\n",
"$$\\sigma = \\frac{L}{R \\cdot b \\cdot d}$$\n",
"* $L$:电极间距(长度);$b$:霍尔片宽度;$d$:霍尔片厚度。\n",
"\n",
"#### 4. 霍尔系数 $R_H$、载流子浓度 $n$ 与迁移率 $\\mu$\n",
"* 霍尔系数:$R_H = |K_H| \\cdot d$\n",
"* 载流子浓度:$n = \\frac{1}{R_H \\cdot e} = \\frac{1}{|K_H| \\cdot e \\cdot d}$($e = 1.602 \\times 10^{-19}\\,\\mathrm{C}$)\n",
"* 载流子迁移率:$\\mu = \\sigma \\cdot R_H = \\sigma \\cdot |K_H| \\cdot d$\n",
"\n",
"#### 5. 回归斜率不确定度与相对误差合成\n",
"* 线性回归斜率 $k$ 的不确定度:$u(k) = |k| \\sqrt{\\frac{1/r^2 - 1}{N - 2}}$\n",
"* 各物理量相对不确定度传递:\n",
"$$u_r(\\sigma) \\approx \\frac{u(R)}{R}, \\quad u_r(K_H) \\approx \\frac{u(k_1)}{k_1}, \\quad u_r(n) = u_r(K_H), \\quad u_r(\\mu) = \\sqrt{u_r^2(\\sigma) + u_r^2(K_H)}$$"
],
"id": "c151d3bfb3ac3774"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from python.utils import scientific_round, linear_regression\n",
"\n",
"print(\"霍尔效应计算与回归分析模块加载完成。\")"
],
"id": "ebdba69fe30f7d93"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 物理常数与霍尔元件几何尺寸"
],
"id": "eb6332ab0ffbedaf"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 基本物理常量\n",
"e_charge = 1.602e-19 # 元电荷 (C)\n",
"mu_0 = 4.0 * math.pi * 1e-7 # 真空磁导率 (T·m/A)\n",
"\n",
"# 霍尔元件几何尺寸 (mm -> m)\n",
"d_mm = 0.095 # 厚度 d (mm)\n",
"b_mm = 0.235 # 宽度 b (mm)\n",
"L_mm = 0.270 # 电极间距 L (mm)\n",
"\n",
"d = d_mm * 1e-3\n",
"b = b_mm * 1e-3\n",
"L = L_mm * 1e-3\n",
"\n",
"# 螺线管磁场比值常数 k_sol = B / Im (T/A)\n",
"k_sol = 0.00209\n",
"\n",
"print(f\"霍尔元件尺寸: L={L_mm} mm, b={b_mm} mm, d={d_mm} mm\")\n",
"print(f\"螺线管比值: k_sol = {k_sol} T/A\")"
],
"id": "964b32703abf7887"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 实验测量数据输入\n",
"> **包含三组数据**:\n",
"> 1. 固定 $I_m$,测量 $V_H$ 随 $I_s$ 的变化;\n",
"> 2. 固定 $I_s$,测量 $V_H$ 随 $I_m$ 的变化;\n",
"> 3. 零磁场下测量 $V_\\sigma$ 随 $I_s$ 的变化。"
],
"id": "bae2c240cece3f2a"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# --- 1. VH vs Is 数据 (固定 Im = 600 mA) ---\n",
"Im_fixed_mA = 600.0\n",
"B_fixed = k_sol * (Im_fixed_mA * 1e-3) # T\n",
"Is_1 = [0.20 * (i + 1) for i in range(10)] # mA: 0.20 ~ 2.00\n",
"# 实测 VH 带符号读数 (mV)\n",
"VH_signed_1 = [-1.52, -3.05, -4.58, -6.11, -7.63, -9.16, -10.68, -12.21, -13.74, -15.26]\n",
"VH_abs_1 = [abs(x) for x in VH_signed_1]\n",
"\n",
"# --- 2. VH vs Im 数据 (固定 Is = 1.50 mA) ---\n",
"Is_fixed_mA = 1.50\n",
"Im_2 = [100.0, 150.0, 200.0, 250.0, 300.0, 350.0, 400.0, 450.0, 500.0, 550.0, 600.0] # mA\n",
"VH_signed_2 = [-1.91, -2.87, -3.82, -4.78, -5.73, -6.69, -7.64, -8.60, -9.55, -10.51, -11.46] # mV\n",
"VH_abs_2 = [abs(x) for x in VH_signed_2]\n",
"\n",
"# --- 3. Vσ vs Is 数据 (零磁场 Im = 0) ---\n",
"Is_3 = list(Is_1) # mA\n",
"Vsigma = [45.2, 90.5, 135.8, 181.0, 226.3, 271.5, 316.8, 362.0, 407.3, 452.5] # mV\n",
"\n",
"print(\"实验数据载入完成。\")"
],
"id": "b944163d5b6fa5f7"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. 线性回归分析与参数计算"
],
"id": "913d723bf7836a79"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 1. 回归 1: VH(mV) vs Is(mA) -> 斜率单位 mV/mA = V/A\n",
"k1, b1, r1, uk1 = map(float, linear_regression(Is_1, VH_abs_1))\n",
"\n",
"# 2. 回归 2: VH(mV) vs Im(mA)\n",
"k2, b2, r2, uk2 = map(float, linear_regression(Im_2, VH_abs_2))\n",
"\n",
"# 3. 回归 3: Vσ(mV) vs Is(mA) -> 样品电阻 R (Ω)\n",
"R_sample, b3, r3, u_R = map(float, linear_regression(Is_3, Vsigma))\n",
"\n",
"# 导电类型判定\n",
"carrier_type = \"P 型 (空穴导电)\" if sum(VH_signed_1)/len(VH_signed_1) > 0 else \"N 型 (电子导电)\"\n",
"\n",
"# 电导率 σ = L / (R · b · d)\n",
"sigma = L / (R_sample * b * d)\n",
"u_r_sigma = abs(u_R / R_sample)\n",
"u_sigma = sigma * u_r_sigma\n",
"sigma_final, u_sigma_final = scientific_round(sigma, u_sigma)\n",
"\n",
"# 霍尔灵敏度 KH = k1 / B_fixed\n",
"KH = k1 / B_fixed\n",
"u_r_KH = abs(uk1 / k1)\n",
"u_KH = KH * u_r_KH\n",
"KH_final, u_KH_final = scientific_round(KH, u_KH)\n",
"\n",
"# 霍尔系数 RH = KH * d\n",
"RH = KH * d\n",
"\n",
"# 载流子浓度 n = 1 / (RH · e)\n",
"n_carrier = 1.0 / (RH * e_charge)\n",
"u_n = n_carrier * u_r_KH\n",
"n_final, u_n_final = scientific_round(n_carrier, u_n)\n",
"\n",
"# 迁移率 μ = σ · RH\n",
"mu = sigma * RH\n",
"u_r_mu = math.sqrt(u_r_sigma**2 + u_r_KH**2)\n",
"u_mu = mu * u_r_mu\n",
"mu_final, u_mu_final = scientific_round(mu, u_mu)\n",
"\n",
"print(\"=\" * 55)\n",
"print(\" 霍 尔 效 应 实 验 结 果 汇 总 \")\n",
"print(\"=\" * 55)\n",
"print(f\"材料导电类型 : {carrier_type}\")\n",
"print(f\"VH-Is 回归斜率 k1 : {k1:.4f} V/A (r={r1:.4f})\")\n",
"print(f\"VH-Im 回归斜率 k2 : {k2:.4f} V/A (r={r2:.4f})\")\n",
"print(f\"样品内阻 R (斜率k3): {R_sample:.4f} Ω (r={r3:.4f})\")\n",
"print(\"-\" * 55)\n",
"print(f\"电导率 σ : {sigma_final} ± {u_sigma_final} S/m\")\n",
"print(f\"霍尔灵敏度 |KH| : {KH_final} ± {u_KH_final} V/(A·T)\")\n",
"print(f\"霍尔系数 RH : {RH:.4e} m³/C\")\n",
"print(f\"载流子浓度 n : {n_final} ± {u_n_final} m⁻³\")\n",
"print(f\"载流子迁移率 μ : {mu_final} ± {u_mu_final} m²/(V·s)\")\n",
"print(\"-\" * 55)\n",
"print(f\"相对不确定度 u_r(σ) : {u_r_sigma*100:.2f}%\")\n",
"print(f\"相对不确定度 u_r(KH): {u_r_KH*100:.2f}%\")\n",
"print(f\"相对不确定度 u_r(μ) : {u_r_mu*100:.2f}%\")\n",
"print(\"=\" * 55)"
],
"id": "7f25b56c710f5a1f"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+434
View File
@@ -0,0 +1,434 @@
import math
"""
Hall Effect Experiment Data Processor
霍尔效应实验数据处理计算器 (直接输入 VH 版)
参考了表面张力系数计算器的高精度与不确定度修约逻辑。
═══════════════════════════════════════════════════════
公式说明:
═══════════════════════════════════════════════════════
1. 霍尔电压 (Hall Voltage):
直接测量输入 VH。
VH > 0 → P 型 (空穴导电)
VH < 0 → N 型 (电子导电)
2. 霍尔效应基本公式 (Hall Effect):
VH = KH · Is · B
其中:
KH = 1 / (n · e · d) — 霍尔灵敏度 [V/(A·T)]
RH = 1 / (n · e) — 霍尔系数 [m³/C]
Is : 工作电流 (霍尔电流) [A]
B : 磁感应强度 [T]
d : 霍尔元件厚度 [m]
n : 载流子浓度 [m⁻³]
e : 元电荷 = 1.602×10⁻¹⁹ [C]
3. 电导率 σ 计算 (Conductivity):
σ = Is · L / (Vσ · b · d)
线性回归 Vσ vs Is,斜率 R_slope = Vσ/Is (即样品电阻 [Ω]),则:
σ = L / (R_slope · b · d) [S/m]
其中:
L : 电压电极间距 (霍尔片长度) [m]
b : 霍尔片宽度 [m]
d : 霍尔片厚度 [m]
4. 载流子浓度 n 与迁移率 μ (Carrier Concentration & Mobility):
n = 1 / (KH · e · d) = 1 / (RH · e) [m⁻³]
μ = σ / (n · e) = σ · RH = σ · KH · d [m²/(V·s)]
5. 螺线管中心磁场 (Solenoid Field):
B = μ₀ · (N / L_sol) · Im
其中:
μ₀ = 4π×10⁻⁷ T·m/A (真空磁导率)
N : 螺线管总匝数
L_sol : 螺线管有效长度 [m]
═══════════════════════════════════════════════════════
不确定度传递公式:
═══════════════════════════════════════════════════════
(a) 线性回归斜率不确定度:
u(k) = |k| · √[(1/r² − 1) / (n − 2)]
其中 r 为相关系数, n 为数据点数
(b) 电导率 σ 的不确定度:
σ = L / (R_slope · b · d)
u_r(σ) = √[(u_R/R)² + (u_L/L)² + (u_b/b)² + (u_d/d)²]
(c) 霍尔灵敏度 KH 的不确定度:
KH = slope₁ / B
u_r(KH) = √[(u_slope₁/slope₁)² + (u_B/B)²]
(d) 载流子浓度 n 的不确定度:
n = 1 / (KH · e · d)
u_r(n) = √[u_r(KH)² + (u_d/d)²]
(e) 载流子迁移率 μ 的不确定度:
μ = σ · KH · d
u_r(μ) = √[u_r(σ)² + u_r(KH)² + (u_d/d)²]
(f) 修约规则:
不确定度保留一位有效数字 (四舍六入五凑偶)
结果末位与不确定度对齐
"""
# ═══════════════════════════════════════════════════════
# 通用工具函数
# ═══════════════════════════════════════════════════════
from utils import (
scientific_round,
linear_regression,
input_float
)
def print_regression(label, k, b, r, u_k, x_unit, y_unit):
"""格式化打印线性回归结果"""
print(f"\n [{label}] 线性回归结果:")
print(f" y = {k:.6f} · x + ({b:.6f})")
print(f" 斜率 k = {k:.6f} {y_unit}/{x_unit}")
print(f" 截距 b = {b:.6f} {y_unit}")
print(f" 相关系数 r = {r:.6f}")
print(f" 斜率不确定度 u(k) = {u_k:.4e}")
# ═══════════════════════════════════════════════════════
# 主程序
# ═══════════════════════════════════════════════════════
def main():
print("════════════════════════════════════════════════════════════")
print(" 霍尔效应实验数据处理计算器 (直接输入VH版)")
print(" Hall Effect Experiment Data Processor")
print("════════════════════════════════════════════════════════════")
# ──────────────────────────────────────────────────
# 物理常量
# ──────────────────────────────────────────────────
e_charge = 1.602e-19 # C (元电荷)
mu_0 = 4.0 * math.pi * 1e-7 # T·m/A (真空磁导率)
print(f"\n 物理常量:")
print(f" e = {e_charge} C")
print(f" μ₀ = {mu_0:.4e} T·m/A")
# ──────────────────────────────────────────────────
# 霍尔元件参数
# ──────────────────────────────────────────────────
print("\n" + "━" * 58)
print(" 霍尔元件几何参数")
print("━" * 58)
d_mm = input_float(" 厚度 d (mm)", 0.095)
b_mm = input_float(" 宽度 b (mm)", 0.235)
L_mm = input_float(" 长度 L (mm)", 0.27)
# 转换为国际单位 m
d = d_mm * 1e-3
b = b_mm * 1e-3
L = L_mm * 1e-3
print(f"\n d = {d_mm} mm = {d:.4e} m")
print(f" b = {b_mm} mm = {b:.4e} m")
print(f" L = {L_mm} mm = {L:.4e} m")
# ──────────────────────────────────────────────────
# 螺线管参数 (计算磁场)
# ──────────────────────────────────────────────────
print("\n" + "━" * 58)
print(" 螺线管参数 (B = k_sol · Im)")
print("━" * 58)
print(" 选择输入方式:")
print(" 1 - 直接输入 B/Im 比值 k_sol (T/A)")
print(" 2 - 输入匝数 N 和有效长度 L_sol")
mode = input(" 请选择 (默认 1): ").strip() or "1"
if mode == "2":
N_turns = input_float(" 螺线管总匝数 N", 2000)
L_sol_mm = input_float(" 螺线管有效长度 (mm)", 200)
L_sol_m = L_sol_mm * 1e-3
k_sol = mu_0 * N_turns / L_sol_m
print(f" k_sol = μ₀·N/L = {mu_0:.4e} × {N_turns:.0f} / {L_sol_m:.4f}")
else:
k_sol = input_float(" 磁场常数 k_sol = B/Im (T/A)", 0.00209)
print(f" ★ 螺线管常数: k_sol = {k_sol:.6e} T/A")
# ══════════════════════════════════════════════════
# 第一部分: VH 与 Is 的关系
# ══════════════════════════════════════════════════
print("\n")
print("▓" * 58)
print(" 第一部分: VH 与 Is 的关系")
print(" 条件: 探头在螺线管中心, Im 恒定")
print("▓" * 58)
Im_fixed_mA = input_float(" 固定励磁电流 Im (mA)", 600)
Im_fixed_A = Im_fixed_mA * 1e-3
B_fixed = k_sol * Im_fixed_A
print(f" 对应磁场 B = k_sol × Im = {B_fixed:.6f} T")
n_pts_1 = 10
Is_1 = [0.20 * (i + 1) for i in range(n_pts_1)] # mA: 0.20 ~ 2.00
print(f"\n 测量要求: 请依次输入各 Is 下对应的霍尔电压 VH (mV)")
print(f" 请注意正负号以判断导电类型。\n")
VH_signed_1 = []
VH_abs_1 = []
for Is_val in Is_1:
vh = input_float(f" Is = {Is_val:.2f} mA → VH (mV)")
VH_signed_1.append(vh)
VH_abs_1.append(abs(vh))
# 打印数据表
print(f"\n{'─' * 46}")
print(f" VH - Is 数据表 (Im = {Im_fixed_mA:.0f} mA, B = {B_fixed:.4f} T)")
print(f"{'─' * 46}")
print(f" {'Is(mA)':>7} │ {'VH带符号(mV)':>12} {'VH绝对值(mV)':>12}")
print(f" {'─' * 42}")
for i in range(n_pts_1):
print(f" {Is_1[i]:>7.2f} │ {VH_signed_1[i]:>12.3f} {VH_abs_1[i]:>12.3f}")
print(f"{'─' * 46}")
# 线性回归: VH(mV) vs Is(mA) —— 使用绝对值 VH
slope_1, intercept_1, r_1, u_slope_1 = map(float, linear_regression(Is_1, VH_abs_1))
print_regression("VH-Is", slope_1, intercept_1, r_1, u_slope_1, "mA", "mV")
# 注: 斜率单位 mV/mA = V/A
# 判断导电类型 (由带符号 VH 的正负判定)
VH_sign_avg = sum(VH_signed_1) / len(VH_signed_1)
if VH_sign_avg > 0:
carrier_type = "P 型 (空穴导电)"
sign_str = "VH > 0"
else:
carrier_type = "N 型 (电子导电)"
sign_str = "VH < 0"
print(f"\n ★ 导电类型判定: {sign_str} → {carrier_type}")
input("\n 按回车继续...")
# ══════════════════════════════════════════════════
# 第二部分: VH 与 Im 的关系
# ══════════════════════════════════════════════════
print("\n")
print("▓" * 58)
print(" 第二部分: VH 与 Im 的关系")
print(" 条件: 探头在螺线管中心, Is 恒定")
print("▓" * 58)
Is_fixed_mA = input_float(" 固定工作电流 Is (mA)", 1.50)
Is_fixed_A = Is_fixed_mA * 1e-3
Im_start = input_float(" Im 起始值 (mA)", 100)
Im_step = input_float(" Im 步长 (mA)", 50)
Im_end = input_float(" Im 终止值 (mA)", 600)
Im_2 = []
val = Im_start
while val <= Im_end + 0.01:
Im_2.append(val)
val += Im_step
n_pts_2 = len(Im_2)
print(f"\n 共 {n_pts_2} 个数据点: Im = {Im_start:.0f} ~ {Im_end:.0f} mA, 步长 {Im_step:.0f} mA")
print(f" 测量要求: 请依次输入各 Im 下对应的霍尔电压 VH (mV)\n")
VH_signed_2 = []
VH_abs_2 = []
for Im_val in Im_2:
vh = input_float(f" Im = {Im_val:.0f} mA → VH (mV)")
VH_signed_2.append(vh)
VH_abs_2.append(abs(vh))
# 打印数据表
print(f"\n{'─' * 46}")
print(f" VH - Im 数据表 (Is = {Is_fixed_mA:.2f} mA)")
print(f"{'─' * 46}")
print(f" {'Im(mA)':>7} │ {'VH带符号(mV)':>12} {'VH绝对值(mV)':>12}")
print(f" {'─' * 42}")
for i in range(n_pts_2):
print(f" {Im_2[i]:>7.0f} │ {VH_signed_2[i]:>12.3f} {VH_abs_2[i]:>12.3f}")
print(f"{'─' * 46}")
# 线性回归: VH(mV) vs Im(mA)
slope_2, intercept_2, r_2, u_slope_2 = map(float, linear_regression(Im_2, VH_abs_2))
print_regression("VH-Im", slope_2, intercept_2, r_2, u_slope_2, "mA", "mV")
input("\n 按回车继续...")
# ══════════════════════════════════════════════════
# 第三部分: 零磁场 Vσ 测量 (电导率)
# ══════════════════════════════════════════════════
print("\n")
print("▓" * 58)
print(" 第三部分: 零磁场 Vσ 测量 (电导率计算)")
print(" 条件: Im = 0, 开关置 Vσ 档")
print("▓" * 58)
# Is 范围与第一部分相同
Is_3 = list(Is_1) # 0.20 ~ 2.00 mA
Vsigma = []
print(f"\n 输入各 Is 下的电压降 Vσ (mV):\n")
for Is_val in Is_3:
vs = input_float(f" Is = {Is_val:.2f} mA → Vσ (mV)")
Vsigma.append(vs)
# 打印数据表
print(f"\n{'─' * 36}")
print(f" Vσ - Is 数据表")
print(f"{'─' * 36}")
print(f" {'Is(mA)':>8} │ {'Vσ(mV)':>10}")
print(f" {'─' * 26}")
for i in range(len(Is_3)):
print(f" {Is_3[i]:>8.2f} │ {Vsigma[i]:>10.4f}")
print(f"{'─' * 36}")
# 线性回归: Vσ(mV) vs Is(mA)
slope_3, intercept_3, r_3, u_slope_3 = map(float, linear_regression(Is_3, Vsigma))
print_regression("Vσ-Is", slope_3, intercept_3, r_3, u_slope_3, "mA", "mV")
print(f" 注: 斜率 = Vσ/Is, 单位 mV/mA = V/A = Ω (样品电阻)")
# ══════════════════════════════════════════════════
# 第四部分: 物理量计算
# ══════════════════════════════════════════════════
print("\n")
print("▓" * 58)
print(" 第四部分: 物理量计算与不确定度分析")
print("▓" * 58)
# ─── 4.1 电导率 σ ───
# σ = L / (R · b · d)
# R = slope_3 (mV/mA = V/A = Ω)
R_sample = slope_3 # Ω
sigma = L / (R_sample * b * d) # S/m
# 不确定度 (此处仅传递回归斜率的不确定度,几何参数视为已知常量)
u_r_R = abs(u_slope_3 / slope_3) if slope_3 != 0 else 0.0
u_r_sigma = u_r_R # 简化: 仅考虑斜率不确定度
u_sigma = abs(sigma) * u_r_sigma
print(f"\n ── 4.1 电导率 σ ──")
print(f" 样品电阻 R = Vσ/Is (斜率) = {R_sample:.6f} Ω")
print(f" σ = L / (R · b · d)")
print(f" = {L:.4e} / ({R_sample:.6f} × {b:.4e} × {d:.4e})")
print(f" = {sigma:.4f} S/m")
print(f" u_r(σ) = u(k₃)/k₃ = {u_r_sigma * 100:.2f}%")
sigma_final, u_sigma_final = scientific_round(sigma, u_sigma)
print(f" ★ σ = {sigma_final} ± {u_sigma_final} S/m")
# ─── 4.2 霍尔灵敏度 KH (由 VH-Is 线性回归) ───
# VH = KH · Is · B → slope₁ = KH · B → KH = slope₁ / B
# slope₁ 单位: mV/mA = V/A
KH = slope_1 / B_fixed # V/(A·T)
u_r_slope1 = abs(u_slope_1 / slope_1) if slope_1 != 0 else 0.0
u_r_KH = u_r_slope1 # B 视为无不确定度
u_KH = abs(KH) * u_r_KH
print(f"\n ── 4.2 霍尔灵敏度 KH (VH-Is) ──")
print(f" KH = slope₁ / B")
print(f" = {slope_1:.6f} / {B_fixed:.6f}")
print(f" = {KH:.4f} V/(A·T)")
print(f" u_r(KH) = {u_r_KH * 100:.2f}%")
KH_final, u_KH_final = scientific_round(abs(KH), u_KH)
print(f" ★ |KH| = {KH_final} ± {u_KH_final} V/(A·T)")
# ─── 交叉验证: 由 VH-Im 线性回归求 KH ───
# VH = KH · Is · k_sol · Im → slope₂ = KH · Is · k_sol
# KH = slope₂ / (Is_fixed_A · k_sol)
KH_check = slope_2 / (Is_fixed_A * k_sol)
print(f"\n ── 交叉验证: KH (VH-Im) ──")
print(f" KH' = slope₂ / (Is · k_sol)")
print(f" = {slope_2:.6f} / ({Is_fixed_A:.4e} × {k_sol:.6e})")
print(f" = {KH_check:.4f} V/(A·T)")
deviation_pct = abs(KH - KH_check) / abs(KH) * 100 if KH != 0 else 0
print(f" 两种方法偏差: {deviation_pct:.2f}%")
# ─── 4.3 霍尔系数 RH ───
RH = abs(KH) * d # m³/C
print(f"\n ── 4.3 霍尔系数 RH ──")
print(f" RH = |KH| × d = {abs(KH):.4f} × {d:.4e}")
print(f" RH = {RH:.4e} m³/C")
# ─── 4.4 载流子浓度 n ───
# n = 1 / (RH · e)
n_carrier = 1.0 / (RH * e_charge)
# u_r(n) = u_r(KH) (d 视为精确)
u_r_n = u_r_KH
u_n = n_carrier * u_r_n
print(f"\n ── 4.4 载流子浓度 n ──")
print(f" n = 1 / (RH · e)")
print(f" = 1 / ({RH:.4e} × {e_charge})")
print(f" = {n_carrier:.4e} m⁻³")
n_final, u_n_final = scientific_round(n_carrier, u_n)
print(f" ★ n = {n_final} ± {u_n_final} m⁻³")
# ─── 4.5 载流子迁移率 μ ───
# μ = σ / (n · e) = σ · RH
mu = sigma / (n_carrier * e_charge)
mu_check = sigma * RH # 验证
u_r_mu = math.sqrt(u_r_sigma ** 2 + u_r_KH ** 2)
u_mu = abs(mu) * u_r_mu
print(f"\n ── 4.5 载流子迁移率 μ ──")
print(f" μ = σ / (n · e)")
print(f" = {sigma:.4f} / ({n_carrier:.4e} × {e_charge})")
print(f" = {mu:.4e} m²/(V·s)")
print(f" 验证: μ = σ · RH = {sigma:.4f} × {RH:.4e} = {mu_check:.4e} m²/(V·s)")
mu_final, u_mu_final = scientific_round(mu, u_mu)
print(f" ★ μ = {mu_final} ± {u_mu_final} m²/(V·s)")
# ══════════════════════════════════════════════════
# 第五部分: 结果汇总
# ══════════════════════════════════════════════════
print("\n")
print("╔══════════════════════════════════════════════════════════════╗")
print("║ 实 验 结 果 汇 总 ║")
print("╠══════════════════════════════════════════════════════════════╣")
print(f"║ ║")
print(f"║ 导电类型: {carrier_type:<47}║")
print(f"║ ║")
print(f"╟────────── 线性回归 ────────────────────────────────────────╢")
print(f"║ VH-Is: k₁ = {slope_1:>10.6f} V/A r = {r_1:>9.6f} ║")
print(f"║ VH-Im: k₂ = {slope_2:>10.6f} V/A r = {r_2:>9.6f} ║")
print(f"║ Vσ-Is: k₃ = {slope_3:>10.6f} Ω r = {r_3:>9.6f} ║")
print(f"╟────────── 物理参数 ────────────────────────────────────────╢")
print(f"║ 电导率 σ = {str(sigma_final):>12} ± {str(u_sigma_final):<10} S/m ║")
print(f"║ 霍尔灵敏度 KH = {str(KH_final):>12} ± {str(u_KH_final):<10} V/(A·T) ║")
print(f"║ 霍尔系数 RH = {RH:>12.4e} m³/C ║")
print(f"║ 载流子浓度 n = {str(n_final):>12} ± {str(u_n_final):<10} m⁻³ ║")
print(f"║ 载流子迁移率 μ = {str(mu_final):>12} ± {str(u_mu_final):<10} m²/(V·s) ║")
print(f"║ ║")
print(f"╟────────── 不确定度 ────────────────────────────────────────╢")
print(f"║ u_r(σ) = {u_r_sigma * 100:>6.2f}% ║")
print(f"║ u_r(KH) = {u_r_KH * 100:>6.2f}% ║")
print(f"║ u_r(n) = {u_r_n * 100:>6.2f}% ║")
print(f"║ u_r(μ) = {u_r_mu * 100:>6.2f}% ║")
print(f"║ ║")
print("╚══════════════════════════════════════════════════════════════╝")
if __name__ == "__main__":
main()
+161
View File
@@ -0,0 +1,161 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 牛顿环曲率半径计算 (逐差法)\n",
"\n",
"本 Notebook 用于通过读数显微镜测得的牛顿环干涉暗环直径平方数据,利用**逐差法**计算平凸透镜的曲率半径 $R$,并完成高精度的合成不确定度评定与结果修约。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 牛顿环曲率半径计算公式\n",
"平凸透镜与平板玻璃构成的空气薄膜发生等厚干涉,第 $m$ 级暗环直径为 $D_m$。第 $i+M$ 级与第 $i$ 级暗环直径平方差为:\n",
"$$\\Delta_i = D_{i+M}^2 - D_i^2 = 4 M R \\lambda$$\n",
"逐差平均值:\n",
"$$\\Delta_{\\mathrm{avg}} = \\frac{1}{M} \\sum_{i=1}^M \\Delta_i$$\n",
"曲率半径 $R$ 为:\n",
"$$R = \\frac{\\Delta_{\\mathrm{avg}}}{4 M \\lambda}$$\n",
"* $\\lambda$:单色光波长(钠黄光默认取 $\\lambda = 589.3\\,\\mathrm{nm} = 0.0005893\\,\\mathrm{mm}$)\n",
"* $M$:逐差跨度(通常第 11~30 环,分为 11~20 环与 21~30 环,跨度 $M = 10$)\n",
"\n",
"#### 2. 不确定度传递公式\n",
"* **A 类不确定度**(针对逐差后的 $\\Delta_i$ 项):\n",
"$$s_\\Delta = \\sqrt{\\frac{1}{M-1} \\sum_{i=1}^M (\\Delta_i - \\Delta_{\\mathrm{avg}})^2}, \\quad u_A(\\Delta) = \\frac{s_\\Delta}{\\sqrt{M}}$$\n",
"* **B 类不确定度**(由读数显微镜测量误差传递):\n",
"设显微镜坐标不确定度为 $u(x) = \\frac{\\Delta_{\\mathrm{inst}}}{\\sqrt{3}}$,则直径 $D = x_R - x_L$ 的平方 $D^2$ 的不确定度满足 $u^2(D^2) = 8 D^2 u^2(x)$。\n",
"由逐差平均传播可得:\n",
"$$u_B^2(\\Delta_{\\mathrm{avg}}) = \\frac{8 u^2(x)}{M^2} \\sum_{i=1}^M (D_i^2 + D_{i+M}^2)$$\n",
"* **合成不确定度传递到曲率半径 $R$**:\n",
"$$u(\\Delta) = \\sqrt{u_A^2(\\Delta) + u_B^2(\\Delta_{\\mathrm{avg}})}, \\quad u(R) = \\frac{u(\\Delta)}{4 M \\lambda}$$"
],
"id": "6a150fa764d0b625"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from decimal import Decimal\n",
"from python.utils import scientific_round\n",
"\n",
"print(\"牛顿环计算模块加载完成。\")"
],
"id": "9218591496bcc1bc"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 实验常数与暗环测量数据输入\n",
"> **提示**:`d_squared_vals` 为第 11 到 30 环的暗环直径平方 $D^2\\,(\\mathrm{mm^2})$(共 20 个数据)。"
],
"id": "924c4d14704f767a"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 钠光波长 λ (mm)\n",
"WAVELENGTH = Decimal(\"0.0005893\")\n",
"\n",
"# 仪器参数\n",
"delta_inst = Decimal(\"0.005\") # 读数显微镜仪器误差限 (mm)\n",
"\n",
"# 第 11 环 ~ 第 30 环的 D^2 数据 (mm^2)\n",
"# 示例数据 (请按实际实验数据替换):\n",
"d_squared_vals = [\n",
" Decimal(\"12.15\"), Decimal(\"13.20\"), Decimal(\"14.35\"), Decimal(\"15.42\"), Decimal(\"16.55\"),\n",
" Decimal(\"17.68\"), Decimal(\"18.72\"), Decimal(\"19.85\"), Decimal(\"20.90\"), Decimal(\"22.05\"),\n",
" Decimal(\"23.15\"), Decimal(\"24.28\"), Decimal(\"25.40\"), Decimal(\"26.50\"), Decimal(\"27.62\"),\n",
" Decimal(\"28.75\"), Decimal(\"29.80\"), Decimal(\"30.95\"), Decimal(\"32.00\"), Decimal(\"33.15\")\n",
"]\n",
"\n",
"print(f\"光波波长 λ: {WAVELENGTH} mm\")\n",
"print(f\"显微镜误差 Δ_inst: {delta_inst} mm\")\n",
"print(f\"已载入暗环平方数据点数: {len(d_squared_vals)}\")"
],
"id": "959e1b03984add7a"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 逐差计算与曲率半径求解"
],
"id": "d92aa19f25481c10"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"M = 10 # 逐差项数\n",
"deltas = []\n",
"sum_d_pairs = Decimal(\"0\")\n",
"\n",
"print(\"--- 逐差过程 (Δ_i = D_{i+10}^2 - D_i^2) ---\")\n",
"for i in range(10):\n",
" d_low_sq = d_squared_vals[i]\n",
" d_high_sq = d_squared_vals[i + 10]\n",
" diff = d_high_sq - d_low_sq\n",
" deltas.append(diff)\n",
" sum_d_pairs += (d_low_sq + d_high_sq)\n",
" print(f\"Δ_{i+11:02d} = D_{i+21}^2 - D_{i+11}^2 = {diff:.3f} mm^2\")\n",
"\n",
"mean_delta = sum(deltas) / Decimal(str(M))\n",
"\n",
"# 曲率半径 R = Δ_avg / (4 * M * λ)\n",
"denominator = Decimal(\"4\") * Decimal(str(M)) * WAVELENGTH\n",
"r_val = mean_delta / denominator\n",
"\n",
"# 不确定度计算\n",
"# 1. A 类不确定度\n",
"variance_delta = sum((x - mean_delta)**2 for x in deltas) / Decimal(str(M - 1))\n",
"s_delta = Decimal(str(math.sqrt(float(variance_delta))))\n",
"u_a_delta = s_delta / Decimal(str(math.sqrt(M)))\n",
"\n",
"# 2. B 类不确定度传播\n",
"u_x = delta_inst / Decimal(str(math.sqrt(3)))\n",
"u_b_delta_sq = (Decimal(\"8\") * (u_x**2) * sum_d_pairs) / (Decimal(str(M))**2)\n",
"u_b_delta = Decimal(str(math.sqrt(float(u_b_delta_sq))))\n",
"\n",
"# 3. 合成不确定度并在 R 上传递\n",
"u_delta_combined = Decimal(str(math.sqrt(float(u_a_delta**2 + u_b_delta**2))))\n",
"u_r = u_delta_combined / denominator\n",
"\n",
"# 4. 科学修约\n",
"r_final, u_final = scientific_round(r_val, u_r)\n",
"\n",
"print(\"\\n\" + \"=\" * 45)\n",
"print(\" 牛 顿 环 曲 率 半 径 计 算 结 果 \")\n",
"print(\"=\" * 45)\n",
"print(f\"逐差平均差值 Δ_avg : {mean_delta:.4f} mm^2\")\n",
"print(f\"差值标准差 s(Δ) : {s_delta:.4f} mm^2\")\n",
"print(f\"A 类不确定度 u_A(Δ) : {u_a_delta:.4f} mm^2\")\n",
"print(f\"B 类不确定度 u_B(Δ) : {u_b_delta:.4f} mm^2\")\n",
"print(\"-\" * 45)\n",
"print(f\"曲率半径 R (原始) : {r_val:.4f} mm ({r_val/1000:.4f} m)\")\n",
"print(f\"合成不确定度 u(R) : {u_r:.4f} mm\")\n",
"print(\"-\" * 45)\n",
"print(f\"★ 最终修约结果 : R = {r_final} ± {u_final} mm\")\n",
"print(\"=\" * 45)"
],
"id": "6258ef3d424cf16f"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+112
View File
@@ -0,0 +1,112 @@
import math
from decimal import Decimal
"""
Newton's Rings Curvature Radius Calculator (Successive Difference Method)
牛顿环曲率半径计算器 (逐差法)
参考 lenth.py 的高精度与不确定度修约逻辑。
"""
from utils import get_decimal_places, scientific_round
def main():
# --- 1. 参数与常量初始化 ---
WAVELENGTH = Decimal("0.0005893") # 钠光波长默认 589.3 nm = 0.0005893 mm
M = 10 # 逐差法的差值项数 (30-20=10)
print("========================================")
print(" 牛顿环曲率半径计算 (逐差法) ")
print("========================================")
print(f"默认波长 λ = {WAVELENGTH} mm (钠光)")
print("参考环数: 第 11 环 到 第 30 环 (共 20 个数据)")
# --- 2. 数据输入 ---
d_squared_vals = []
data_strs = []
print("\n[第一步] 请输入暗环直径平方 D^2 (单位: mm^2)")
print("支持粘贴或逐个输入,精确到小数点后三位。")
for i in range(11, 31):
while True:
try:
user_input = input(f"D_{i:02d}^2 = ").strip()
if not user_input:
continue
val = Decimal(user_input)
d_squared_vals.append(val)
data_strs.append(user_input)
break
except Exception:
print("无效输入!请输入正确的直径平方值(如 12.345)。")
print("\n[第二步] 仪器参数输入")
res_input = input("请输入仪器分度值 (默认 0.01 mm): ").strip() or "0.01"
delta_inst_input = input("请输入仪器误差 Δ_inst (默认 0.005 mm): ").strip() or "0.005"
res = Decimal(res_input)
delta_inst = Decimal(delta_inst_input)
# --- 3. 逐差计算 ---
# Δ_i = D_{i+M}^2 - D_i^2 (i = 11...20)
deltas = []
sum_d_pairs = Decimal("0") # 用于 B 类不确定度传播: sum(D_low^2 + D_high^2)
print("\n--- 逐差过程 ---")
for i in range(10):
d_low_sq = d_squared_vals[i]
d_high_sq = d_squared_vals[i + 10]
diff = d_high_sq - d_low_sq
deltas.append(diff)
sum_d_pairs += (d_low_sq + d_high_sq)
print(f"Δ_{i+11:02d} = D_{i+21}^2 - D_{i+11}^2 = {diff} mm^2")
mean_delta = sum(deltas) / Decimal(str(M))
# --- 4. 曲率半径计算 ---
# R = Δ_avg / (4 * M * λ)
# M = 10, 所以分母是 40 * λ
denominator = Decimal("4") * Decimal(str(M)) * WAVELENGTH
r_val = mean_delta / denominator
# --- 5. 不确定度计算 ---
# (1) A 类不确定度 u_A (针对逐差后的 Δ)
variance_delta = sum((x - mean_delta)**2 for x in deltas) / Decimal(str(M - 1))
s_delta = Decimal(str(math.sqrt(float(variance_delta))))
u_a_delta = s_delta / Decimal(str(math.sqrt(M)))
# (2) B 类不确定度 u_B (传播自读数显微镜的仪器误差)
# 推导过程:
# u(x) = delta_inst / sqrt(3)
# u(D^2) = sqrt( (2D u_x)^2 + (2D u_x)^2 ) = 2 * sqrt(2) * D * u_x
# u(D^2)^2 = 8 * D^2 * u_x^2
# u(Δ)^2 = u(D_high^2)^2 + u(D_low^2)^2 = 8 * u_x^2 * (D_high^2 + D_low^2)
# u(Δ_avg)^2 = (1/M^2) * sum( u(Δ_i)^2 ) = (8 * u_x^2 / M^2) * sum_d_pairs
u_x = delta_inst / Decimal(str(math.sqrt(3)))
u_b_delta_sq = (Decimal("8") * (u_x**2) * sum_d_pairs) / (Decimal(str(M))**2)
u_b_delta = Decimal(str(math.sqrt(float(u_b_delta_sq))))
# (3) 合成不确定度 u(Δ) 并在 R 上传播
u_delta_combined = Decimal(str(math.sqrt(float(u_a_delta**2 + u_b_delta**2))))
u_r = u_delta_combined / denominator
# --- 6. 修约与展示 ---
r_final, u_final = scientific_round(r_val, u_r)
print("\n--- 中间统计结果 (高精度) ---")
print(f"平均差值 Δ_avg: {mean_delta:.6f} mm^2")
print(f"Δ 的标准差 s: {s_delta:.6f}")
print(f"Δ 的 A 类不确定度 u_A(Δ): {u_a_delta:.6f}")
print(f"Δ 的 B 类不确定度 u_B(Δ): {u_b_delta:.6f}")
print("\n--- 最终计算结果 (R) ---")
print(f"曲率半径 R (原始): {r_val:.4f} mm")
print(f"R 的合成不确定度 u(R): {u_r:.4f} mm")
print("\n========================================")
print(" 最终修约结果 (四舍六入五凑偶)")
print(f" R = {r_final} ± {u_final} mm")
print("========================================")
if __name__ == "__main__":
main()
+158
View File
@@ -0,0 +1,158 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 声速测量计算器 (逐差法)\n",
"\n",
"本 Notebook 用于通过**干涉法(驻波法)**与**相位法(李萨如图形法)**测得的接收器位移坐标,利用**逐差法**计算超声波在空气中的波长 $\\lambda$、实际声速 $v$,并与理论声速进行对比和不确定度评定。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 理论声速公式\n",
"在摄氏温度 $t\\,({}^\\circ\\mathrm{C})$ 下,空气中理想声速为:\n",
"$$v_t = 331.45 \\sqrt{1 + \\frac{t}{273.15}} \\quad (\\mathrm{m/s})$$\n",
"\n",
"#### 2. 逐差法测波长 $\\lambda$\n",
"两组数据各测 12 个极值或特定相位位置坐标 $x_1, x_2, \\dots, x_{12}$,分成两组逐差:\n",
"$$\\Delta x_i = x_{i+6} - x_i \\quad (i = 1, 2, \\dots, 6), \\quad \\Delta x_{\\mathrm{avg}} = \\frac{1}{6} \\sum_{i=1}^6 \\Delta x_i$$\n",
"* **干涉法(驻波法)**:相邻波腹间距为 $\\lambda/2$,6 个间隔对应 $\\Delta x = 6 \\times (\\lambda/2) = 3\\lambda$,故:\n",
"$$\\lambda = \\frac{\\Delta x_{\\mathrm{avg}}}{3}$$\n",
"* **相位法(李萨如法)**:相邻同向直线相位差为 $2\\pi$,对应间距为 $\\lambda$,6 个间隔对应 $\\Delta x = 6\\lambda$,故:\n",
"$$\\lambda = \\frac{\\Delta x_{\\mathrm{avg}}}{6}$$\n",
"\n",
"#### 3. 声速与不确定度传递公式\n",
"实验测得声速为 $v = f \\cdot \\lambda$。\n",
"* 逐差平均值的 A 类不确定度:$u_A(\\Delta x_{\\mathrm{avg}}) = \\frac{s_\\Delta}{\\sqrt{6}}$\n",
"* 逐差平均值的 B 类不确定度:$u_B(\\Delta x_{\\mathrm{avg}}) = \\sqrt{\\frac{2}{6}} \\frac{\\Delta_{\\mathrm{inst}}}{\\sqrt{3}} = \\frac{\\Delta_{\\mathrm{inst}}}{3}$\n",
"* 合成不确定度:$u_c(\\Delta x_{\\mathrm{avg}}) = \\sqrt{u_A^2 + u_B^2}$\n",
"* 波长及声速不确定度(忽略频率 $f$ 极小的不确定度):\n",
"$$u(\\lambda) = \\frac{u_c(\\Delta x_{\\mathrm{avg}})}{k}, \\quad u(v) = f \\cdot u(\\lambda)$$"
],
"id": "db386d820ed39819"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from decimal import Decimal\n",
"from python.utils import scientific_round\n",
"\n",
"print(\"声速计算模块加载完成。\")"
],
"id": "72c0a986ef718706"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 实验条件与测量数据输入\n",
"> **提示**:可在此输入环境温度、激励信号源频率,以及干涉法和相位法分别测得的 12 个坐标值 $x_i\\,(\\mathrm{mm})$。"
],
"id": "b2da551f9b00370d"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 实验环境参数\n",
"t_celsius = 24.0 # 环境温度 (℃)\n",
"freq = 37000.0 # 谐振超声波频率 (Hz)\n",
"delta_inst = Decimal(\"0.02\") # 游标卡尺/测微鼓轮分度值误差 (mm)\n",
"\n",
"# 1. 干涉法 (驻波法) 12 个坐标 (mm)\n",
"x_vals_interference = [\n",
" Decimal(\"10.20\"), Decimal(\"14.85\"), Decimal(\"19.50\"), Decimal(\"24.15\"), Decimal(\"28.80\"), Decimal(\"33.45\"),\n",
" Decimal(\"38.10\"), Decimal(\"42.75\"), Decimal(\"47.40\"), Decimal(\"52.05\"), Decimal(\"56.70\"), Decimal(\"61.35\")\n",
"]\n",
"\n",
"# 2. 相位法 (李萨如图形法) 12 个坐标 (mm)\n",
"x_vals_phase = [\n",
" Decimal(\"12.00\"), Decimal(\"21.30\"), Decimal(\"30.60\"), Decimal(\"39.90\"), Decimal(\"49.20\"), Decimal(\"58.50\"),\n",
" Decimal(\"67.80\"), Decimal(\"77.10\"), Decimal(\"86.40\"), Decimal(\"95.70\"), Decimal(\"105.00\"), Decimal(\"114.30\")\n",
"]\n",
"\n",
"v_theory = 331.45 * math.sqrt(1 + t_celsius / 273.15)\n",
"print(f\"当前温度 {t_celsius} ℃ 下的理论声速 v_t: {v_theory:.2f} m/s\")"
],
"id": "634f5ee7bd5300e5"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 逐差法处理与声速不确定度评定"
],
"id": "223b20661658522d"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def process_speed_of_sound(method_name, x_vals, f, k, delta_inst):\n",
" M = 6\n",
" deltas = []\n",
" for i in range(M):\n",
" diff = x_vals[i + M] - x_vals[i]\n",
" deltas.append(diff)\n",
" mean_delta = sum(deltas) / Decimal(str(M))\n",
" \n",
" # 计算波长 (mm -> m)\n",
" wavelength_mm = mean_delta / Decimal(str(k))\n",
" wavelength_m = wavelength_mm / Decimal(\"1000\")\n",
" velocity = Decimal(str(f)) * wavelength_m\n",
" \n",
" # 不确定度分析\n",
" variance_delta = sum((d - mean_delta)**2 for d in deltas) / Decimal(str(M - 1))\n",
" s_delta = Decimal(str(math.sqrt(float(variance_delta))))\n",
" u_a_delta = s_delta / Decimal(str(math.sqrt(M)))\n",
" \n",
" u_x = delta_inst / Decimal(str(math.sqrt(3)))\n",
" u_b_delta = Decimal(str(math.sqrt(2.0 / M))) * u_x\n",
" u_delta_combined = Decimal(str(math.sqrt(float(u_a_delta**2 + u_b_delta**2))))\n",
" \n",
" u_wavelength_mm = u_delta_combined / Decimal(str(k))\n",
" u_wavelength_m = u_wavelength_mm / Decimal(\"1000\")\n",
" u_velocity = Decimal(str(f)) * u_wavelength_m\n",
" \n",
" v_final, uv_final = scientific_round(velocity, u_velocity)\n",
" \n",
" print(\"=\" * 45)\n",
" print(f\" {method_name} 计算结果 \")\n",
" print(\"=\" * 45)\n",
" print(f\"逐差平均位移 Δx_avg : {mean_delta:.4f} mm\")\n",
" print(f\"位移标准差 s(Δx) : {s_delta:.4f} mm\")\n",
" print(f\"声波波长 λ : {wavelength_mm:.4f} mm\")\n",
" print(f\"波长不确定度 u(λ) : {u_wavelength_mm:.4f} mm\")\n",
" print(f\"实验声速 v (原始) : {velocity:.2f} m/s\")\n",
" print(f\"声速合成不确定度 u(v): {u_velocity:.2f} m/s\")\n",
" rel_error = abs(float(velocity) - v_theory) / v_theory * 100\n",
" print(f\"与理论声速相对误差 : {rel_error:.2f}%\")\n",
" print(\"-\" * 45)\n",
" print(f\"★ 最终修约结果 : v = {v_final} ± {uv_final} m/s\")\n",
" print(\"=\" * 45 + \"\\n\")\n",
"\n",
"# 处理两种方法\n",
"process_speed_of_sound(\"干涉法 (驻波法)\", x_vals_interference, freq, 3, delta_inst)\n",
"process_speed_of_sound(\"相位法 (李萨如法)\", x_vals_phase, freq, 6, delta_inst)"
],
"id": "70554a3d5158f78e"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+144
View File
@@ -0,0 +1,144 @@
import math
from decimal import Decimal
"""
Speed of Sound Calculator (Successive Difference Method)
声速测量计算器 (逐差法)
参考了 Newton's rings.py 的高精度与不确定度修约逻辑。
计算公式说明:
1. 理论声速公式:
v_t = 331.45 * sqrt(1 + t / 273.15)
其中 t 为摄氏温度。
2. 逐差法计算波长 λ:
本实验两组数据均为 12 个点,分成两组进行逐差:Δx_i = x_{i+6} - x_i (i=1..6)
- 干涉法 (驻波法) 找振幅最大处:相邻两次最大处间距为 λ/2
因此 Δx = 6 * (λ/2) = 3λ => λ = Δx_avg / 3
- 相位法 (李萨如图像) 变为相同方向直线:相邻两次相位改变 2π,间距为 λ
因此 Δx = 6 * λ => λ = Δx_avg / 6
3. 声速公式:
v = f * λ
4. 不确定度传递公式:
- Δx_avg 的 A 类不确定度: u_A(Δx_avg) = S_Δ / sqrt(M) (其中 S_Δ 为逐差后 Δx 的标准差, M=6)
- 坐标 x 的 B 类不确定度: u_B(x) = Δ_inst / sqrt(3) (假设均匀分布)
- 逐差平均值的 B 类不确定度传播: u_B(Δx_avg) = sqrt(2/M) * u_B(x)
- Δx_avg 的合成不确定度: u_c(Δx_avg) = sqrt(u_A^2 + u_B^2)
- 波长 λ 的不确定度:
干涉法 u(λ) = u_c(Δx_avg) / 3
相位法 u(λ) = u_c(Δx_avg) / 6
- 声速 v 的不确定度 (忽略 f 的极小不确定度): u(v) = f * u(λ)
"""
from utils import scientific_round
def calculate_method(method_name, f, k, delta_inst):
print(f"\n========================================")
print(f" {method_name} ")
print(f"========================================")
print("请输入12个坐标数据 (单位: mm)。")
x_vals = []
for i in range(1, 13):
while True:
try:
val_str = input(f"x_{i:02d} = ").strip()
if not val_str:
continue
x_vals.append(Decimal(val_str))
break
except Exception:
print("无效输入!请输入正确的数值。")
# 1. 逐差计算
M = 6
deltas = []
print("\n--- 逐差过程 ---")
for i in range(M):
diff = x_vals[i + M] - x_vals[i]
deltas.append(diff)
print(f"Δx_{i+1} = x_{i+M+1} - x_{i+1} = {x_vals[i+M]} - {x_vals[i]} = {diff} mm")
mean_delta = sum(deltas) / Decimal(str(M))
# 2. 波长与声速计算
# 将毫米转换为米计算速度
wavelength_mm = mean_delta / Decimal(str(k))
wavelength_m = wavelength_mm / Decimal("1000")
velocity = Decimal(str(f)) * wavelength_m
# 3. 不确定度计算
# u_A
variance_delta = sum((d - mean_delta)**2 for d in deltas) / Decimal(str(M - 1))
s_delta = Decimal(str(math.sqrt(float(variance_delta))))
u_a_delta = s_delta / Decimal(str(math.sqrt(M)))
# u_B
u_x = delta_inst / Decimal(str(math.sqrt(3)))
u_b_delta = Decimal(str(math.sqrt(2.0 / M))) * u_x
# u_c(Δx_avg)
u_delta_combined = Decimal(str(math.sqrt(float(u_a_delta**2 + u_b_delta**2))))
# 传播到波长和声速
u_wavelength_mm = u_delta_combined / Decimal(str(k))
u_wavelength_m = u_wavelength_mm / Decimal("1000")
u_velocity = Decimal(str(f)) * u_wavelength_m
# 4. 修约与展示
v_final, uv_final = scientific_round(velocity, u_velocity)
print("\n--- 中间统计结果 (高精度) ---")
print(f"平均差值 Δx_avg: {mean_delta:.6f} mm")
print(f"Δx 的标准差 S_Δ: {s_delta:.6f} mm")
print(f"Δx_avg 的 A 类不确定度 u_A: {u_a_delta:.6f} mm")
print(f"Δx_avg 的 B 类不确定度 u_B: {u_b_delta:.6f} mm")
print(f"波长 λ: {wavelength_mm:.6f} mm")
print(f"波长的不确定度 u(λ): {u_wavelength_mm:.6f} mm")
print("\n========================================")
print(f" {method_name} 最终结果 (四舍六入五凑偶)")
print(f" v = {v_final} ± {uv_final} m/s")
print("========================================")
def main():
print("========================================")
print(" 声速测量计算器 ")
print("========================================")
t_input = input("请输入环境温度 t (℃) [默认 24]: ").strip() or "24"
f_input = input("请输入谐振波频率 f (Hz) [默认 37000]: ").strip() or "37000"
delta_inst_input = input("请输入游标卡尺/测微鼓轮分度值误差 Δ_inst (mm) [默认 0.02]: ").strip() or "0.02"
t = float(t_input)
f = float(f_input)
delta_inst = Decimal(delta_inst_input)
# 计算理论声速
v_t = 331.45 * math.sqrt(1 + t / 273.15)
print(f"\n理论声速 v_t = {v_t:.2f} m/s (温度 {t} ℃)")
while True:
print("\n请选择计算方法:")
print("1. 干涉法 (驻波法) - 振幅最大处")
print("2. 相位法 (李萨如法) - 相同方向直线")
print("3. 退出")
choice = input("请输入选项 (1/2/3): ").strip()
if choice == '1':
# 干涉法 k = 3 (Δx_avg = 3λ)
calculate_method("干涉法 (振幅最大处)", f, 3, delta_inst)
elif choice == '2':
# 相位法 k = 6 (Δx_avg = 6λ)
calculate_method("相位法 (相同方向直线)", f, 6, delta_inst)
elif choice == '3':
print("退出程序。")
break
else:
print("无效选项,请重新输入。")
if __name__ == "__main__":
main()
+190
View File
@@ -0,0 +1,190 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 拉脱法测液体表面张力系数计算器\n",
"\n",
"本 Notebook 用于通过力敏传感器测定拉脱法实验中液体(水)的表面张力系数 $\\alpha$。包含砝码电压标定(线性回归求传感器灵敏度 $K$)、拉脱峰值电压与吊环内外径统计、不确定度合成及规范修约。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 表面张力系数计算公式\n",
"当薄壁圆环从液体表面被拉脱的一瞬间,所受的最大液体表面张力与圆环内外周长成正比:\n",
"$$\\alpha = \\frac{F}{\\pi (d_1 + d_2)}$$\n",
"* $F$:最大拉脱力(通过力敏传感器测得 $F = U_{\\mathrm{pull}} / K$)\n",
"* $K$:力敏传感器灵敏度 $(\\mathrm{V/N})$ 或 $(\\mathrm{mV/N})$\n",
"* $d_1, d_2$:金属圆环的内径与外径\n",
"\n",
"#### 2. 力敏传感器灵敏度标定\n",
"使用单重为 $m$ 的标准小砝码增重与减重 $i$ 个($i = 0, 1, \\dots, 5$),各测得对应的输出电压 $U_{1,i}, U_{2,i}$。取增减重平均值:\n",
"$$\\bar{U}_i = \\frac{U_{1,i} + U_{2,i}}{2}, \\quad F_i = i \\cdot m \\cdot g$$\n",
"使用最小二乘线性回归对 $(F_i, \\bar{U}_i)$ 拟合直线 $U = K \\cdot F + b$,斜率即为灵敏度 $K$,其标准不确定度记为 $u(K)$。\n",
"\n",
"#### 3. 不确定度合成与传递\n",
"* 拉脱力 $F$ 的相对不确定度:\n",
"$$u_r(F) = \\sqrt{ \\left(\\frac{u_U}{\\bar{U}_{\\mathrm{pull}}}\\right)^2 + \\left(\\frac{u_K}{K}\\right)^2 }$$\n",
"* 直径和 $(d_1 + d_2)$ 的不确定度:\n",
"$$u(d_1 + d_2) = \\sqrt{u^2(d_1) + u^2(d_2)}, \\quad u_r(d_1+d_2) = \\frac{u(d_1 + d_2)}{d_1 + d_2}$$\n",
"* 表面张力系数 $\\alpha$ 的总相对不确定度与绝对不确定度:\n",
"$$u_r(\\alpha) = \\sqrt{u_r^2(F) + u_r^2(d_1 + d_2)}, \\quad u(\\alpha) = \\alpha \\cdot u_r(\\alpha)$$"
],
"id": "781711c13d45a52a"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from decimal import Decimal\n",
"from python.utils import scientific_round, calculate_stats, linear_regression\n",
"\n",
"print(\"表面张力系数模块加载完成。\")"
],
"id": "d1f8bddcdc7a754a"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 传感器砝码标定数据输入与拟合\n",
"> **提示**:可在此输入单个小砝码质量 `m_mass_g` 以及增重、减重各 6 个点对应的标定电压。"
],
"id": "6a7bf3a6389e57db"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"G = Decimal(\"9.80\") # 重力加速度 (m/s^2)\n",
"PI = Decimal(str(math.pi))\n",
"\n",
"# 单个小砝码质量 (g)\n",
"m_mass_g = Decimal(\"0.50\")\n",
"m_mass_kg = m_mass_g / Decimal(\"1000\")\n",
"\n",
"# 标定电压 (0~5个砝码, 单位与后续拉脱电压保持统一即可, 如 V 或 mV)\n",
"U_calib_1 = [Decimal(\"0.00\"), Decimal(\"0.052\"), Decimal(\"0.104\"), Decimal(\"0.155\"), Decimal(\"0.207\"), Decimal(\"0.259\")] # 增重\n",
"U_calib_2 = [Decimal(\"0.00\"), Decimal(\"0.051\"), Decimal(\"0.103\"), Decimal(\"0.156\"), Decimal(\"0.208\"), Decimal(\"0.260\")] # 减重\n",
"\n",
"# 计算平均电压与外力\n",
"U_calib_avg = [(U_calib_1[i] + U_calib_2[i]) / Decimal(\"2\") for i in range(6)]\n",
"F_calib = [Decimal(str(i)) * m_mass_kg * G for i in range(6)]\n",
"\n",
"# 线性回归拟合灵敏度 K\n",
"K, K_b, r, u_K = linear_regression(F_calib, U_calib_avg)\n",
"\n",
"print(\"=\" * 45)\n",
"print(\" 传 感 器 标 定 拟 合 结 果 \")\n",
"print(\"=\" * 45)\n",
"print(f\"灵敏度斜率 K : {K:.6f} (电压单位/N)\")\n",
"print(f\"截距 b : {K_b:.6f}\")\n",
"print(f\"相关系数 r : {r:.6f}\")\n",
"print(f\"斜率不确定度 u_K: {u_K:.6e}\")"
],
"id": "db8e4e72f93077d5"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 拉脱实验数据与圆环几何尺寸输入"
],
"id": "37706b6c98e4d762"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 仪器允差\n",
"delta_U = Decimal(\"0.001\") # 电压表仪器误差\n",
"delta_d = Decimal(\"0.02\") # 游标卡尺仪器误差 (mm)\n",
"\n",
"# 6次测量数据列表\n",
"U_pull_vals = [Decimal(\"0.215\"), Decimal(\"0.214\"), Decimal(\"0.216\"), Decimal(\"0.215\"), Decimal(\"0.213\"), Decimal(\"0.215\")]\n",
"d1_vals = [Decimal(\"33.10\"), Decimal(\"33.12\"), Decimal(\"33.08\"), Decimal(\"33.10\"), Decimal(\"33.14\"), Decimal(\"33.10\")] # 内径 (mm)\n",
"d2_vals = [Decimal(\"35.20\"), Decimal(\"35.22\"), Decimal(\"35.18\"), Decimal(\"35.20\"), Decimal(\"35.22\"), Decimal(\"35.20\")] # 外径 (mm)\n",
"\n",
"# 统计各量\n",
"U_pull_mean, U_pull_u = calculate_stats(U_pull_vals, delta_U)[:2]\n",
"d1_mean, d1_u = calculate_stats(d1_vals, delta_d)[:2]\n",
"d2_mean, d2_u = calculate_stats(d2_vals, delta_d)[:2]\n",
"\n",
"print(f\"拉脱平均电压 U_pull: {U_pull_mean:.4f} ± {U_pull_u:.4f}\")\n",
"print(f\"圆环平均内径 d1 : {d1_mean:.3f} ± {d1_u:.3f} mm\")\n",
"print(f\"圆环平均外径 d2 : {d2_mean:.3f} ± {d2_u:.3f} mm\")"
],
"id": "4898cff018c8803b"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. 表面张力系数计算与不确定度修约"
],
"id": "188a7b2b3dc5b54"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 计算拉脱力 F (N)\n",
"F_pull_mean = U_pull_mean / K\n",
"\n",
"# 换算为标准国际单位 m\n",
"d1_m = d1_mean / Decimal(\"1000\")\n",
"d2_m = d2_mean / Decimal(\"1000\")\n",
"d1_u_m = d1_u / Decimal(\"1000\")\n",
"d2_u_m = d2_u / Decimal(\"1000\")\n",
"d_sum = d1_m + d2_m\n",
"\n",
"# 表面张力系数 α = F / [π * (d1 + d2)]\n",
"alpha_val = F_pull_mean / (PI * d_sum)\n",
"\n",
"# 不确定度合成传递\n",
"u_r_F_sq = (U_pull_u / U_pull_mean)**2 + (u_K / K)**2\n",
"u_r_F = Decimal(str(math.sqrt(float(u_r_F_sq))))\n",
"\n",
"u_d_sum = Decimal(str(math.sqrt(float(d1_u_m**2 + d2_u_m**2))))\n",
"u_r_d_sum = u_d_sum / d_sum\n",
"\n",
"u_r_alpha = Decimal(str(math.sqrt(float(u_r_F**2 + u_r_d_sum**2))))\n",
"alpha_u = alpha_val * u_r_alpha\n",
"\n",
"# 科学修约\n",
"alpha_final, u_final = scientific_round(alpha_val, alpha_u)\n",
"\n",
"print(\"=\" * 45)\n",
"print(\" 表 面 张 力 系 数 计 算 结 果 \")\n",
"print(\"=\" * 45)\n",
"print(f\"最大拉脱力 F : {F_pull_mean:.6f} N\")\n",
"print(f\"圆环周长项 (d1+d2): {(d_sum*1000):.3f} mm\")\n",
"print(f\"表面张力系数 α (原始): {alpha_val:.6f} N/m\")\n",
"print(\"-\" * 45)\n",
"print(f\"相对不确定度 u_r : {u_r_alpha * 100:.2f}%\")\n",
"print(f\"绝对不确定度 u_α : {alpha_u:.6f} N/m\")\n",
"print(\"-\" * 45)\n",
"print(f\"★ 最终修约结果 : α = {alpha_final} ± {u_final} N/m\")\n",
"print(\"=\" * 45)"
],
"id": "74791d410688e40a"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+182
View File
@@ -0,0 +1,182 @@
import math
from decimal import Decimal
"""
Surface Tension Coefficient Calculator (Pull-off Method)
拉脱法测液体表面张力系数计算器
参考了杨氏模量及粘滞系数代码的高精度与不确定度修约逻辑。
公式说明:
1. 表面张力系数计算公式:
α = F / [π * (d1 + d2)]
其中:
F : 拉脱力,通过传感器测得 F = U / K (K为传感器灵敏度)
d1 : 铁环内径
d2 : 铁环外径
2. 传感器灵敏度 K (通过砝码标定):
测得 2 组不同砝码个数 i (0~5) 下的电压 U1_i 与 U2_i (通常为增重与减重过程)。
取其平均值 U_avg_i = (U1_i + U2_i) / 2。
设单个砝码质量为 m,则受力 F_i = i * m * g。
使用最小二乘法对 (F_i, U_avg_i) 进行线性回归,斜率即为灵敏度 K (V/N)。
3. 不确定度传递公式 (相对不确定度):
假定 K 的不确定度 u_K 通过线性回归标准差求得。
拉脱力 F 的平均值: F_mean = U_pull_mean / K
拉脱力 F 的不确定度 (相对不确定度):
u_r(F) = sqrt( (u_U / U_pull_mean)^2 + (u_K / K)^2 )
内外径和(d1+d2)的不确定度:
u_d_sum = sqrt( u_d1^2 + u_d2^2 )
u_r(d_sum) = u_d_sum / (d1_mean + d2_mean)
总相对不确定度:
u_r(α) = u_α / α = sqrt( u_r(F)^2 + u_r(d_sum)^2 )
绝对不确定度:
u_α = α * u_r(α)
对于多次测量量 X 的不确定度:
u_X = sqrt( u_A,X^2 + u_B,X^2 )
u_A,X = s_X / sqrt(n)
u_B,X = Δ_inst / sqrt(3)
"""
from utils import (
scientific_round,
calculate_stats,
linear_regression,
input_data_group
)
def main():
print("========================================")
print(" 拉脱法测水表面张力系数计算器 ")
print("========================================")
# --- 1. 常量设置 ---
G = Decimal("9.80") # 重力加速度 m/s^2
PI = Decimal(str(math.pi))
print(f"重力加速度 g = {G} m/s^2")
print(f"圆周率 π ≈ {PI:.5f}")
print("\n--- 砝码参数与标定 ---")
m_default = "0.5"
m_input = input(f"单个小砝码质量 m (g, 默认 {m_default}): ").strip() or m_default
m_mass = Decimal(m_input) / Decimal("1000") # 转为 kg
print("\n请输入力敏传感器标定电压 (共 2 组,0~5 个小砝码,例如:第 1 组为增重,第 2 组为减重):")
print("\n--- 输入第 1 组标定电压 (U1) ---")
U_calib_1 = []
for i in range(6):
while True:
try:
val = input(f"第1组 - 放 {i} 个砝码时的电压 U1 (V或mV, 请统一单位) = ").strip()
if not val: continue
U_calib_1.append(Decimal(val))
break
except Exception:
print("输入无效,请输入数字。")
print("\n--- 输入第 2 组标定电压 (U2) ---")
U_calib_2 = []
for i in range(6):
while True:
try:
val = input(f"第2组 - 放 {i} 个砝码时的电压 U2 (V或mV, 请统一单位) = ").strip()
if not val: continue
U_calib_2.append(Decimal(val))
break
except Exception:
print("输入无效,请输入数字。")
# 计算两组的平均电压并生成对应的受力
U_calib_avg = []
F_calib = []
for i in range(6):
avg_val = (U_calib_1[i] + U_calib_2[i]) / Decimal("2")
U_calib_avg.append(avg_val)
F_calib.append(Decimal(str(i)) * m_mass * G)
# 打印标定数据对照表
print("\n" + "-"*65)
print(f"{'砝码数':<6} | {'受力 F (N)':<12} | {'第1组 U1':<10} | {'第2组 U2':<10} | {'平均 U_avg':<10}")
print("-"*65)
for i in range(6):
print(f"{i:<8} | {F_calib[i]:<12.6f} | {U_calib_1[i]:<10.4f} | {U_calib_2[i]:<10.4f} | {U_calib_avg[i]:<10.4f}")
print("-"*65)
# 计算灵敏度 K
K, K_b, r, u_K = linear_regression(F_calib, U_calib_avg)
print(f"\n[标定结果] 传感器灵敏度 K = {K:.6f}, 截距 = {K_b:.6f}")
print(f"线性相关系数 r = {r:.6f}, 斜率不确定度 u_K = {u_K:.6e}")
# --- 2. 拉脱测量与仪器误差输入 ---
print("\n--- 输入仪器误差 Δ_inst ---")
delta_U = Decimal(input("电压 U 的仪器误差 (默认 0.001): ").strip() or "0.001")
delta_d = Decimal(input("游标卡尺测量内外径的仪器误差 (mm, 默认 0.02): ").strip() or "0.02")
# 输入拉脱电压 U_pull (6次)
U_pull_vals = input_data_group("拉脱时的电压差/峰值电压 U_pull", 6, "同标定电压单位")
U_pull_mean, U_pull_u = calculate_stats(U_pull_vals, delta_U)[:2]
# 输入内径 d1 (6次)
d1_vals = input_data_group("铁环内径 d1", 6, "mm")
d1_mean, d1_u = calculate_stats(d1_vals, delta_d)[:2]
# 输入外径 d2 (6次)
d2_vals = input_data_group("铁环外径 d2", 6, "mm")
d2_mean, d2_u = calculate_stats(d2_vals, delta_d)[:2]
# --- 3. 表面张力系数计算 ---
# F = U / K
F_pull_mean = U_pull_mean / K
# 统一转化内径、外径为国际标准单位 m
d1_m = d1_mean / Decimal("1000")
d2_m = d2_mean / Decimal("1000")
d1_u_m = d1_u / Decimal("1000")
d2_u_m = d2_u / Decimal("1000")
# α = F / [π * (d1 + d2)]
d_sum = d1_m + d2_m
alpha_val = F_pull_mean / (PI * d_sum)
# --- 4. 不确定度传播 ---
# u_r(F) = sqrt( (u_U / U_pull_mean)^2 + (u_K / K)^2 )
u_r_F_sq = (U_pull_u / U_pull_mean)**2 + (u_K / K)**2
u_r_F = Decimal(str(math.sqrt(float(u_r_F_sq))))
# u(d1 + d2)
u_d_sum = Decimal(str(math.sqrt(float(d1_u_m**2 + d2_u_m**2))))
u_r_d_sum = u_d_sum / d_sum
# u_r(α) = sqrt( u_r(F)^2 + u_r(d_sum)^2 )
u_r_alpha = Decimal(str(math.sqrt(float(u_r_F**2 + u_r_d_sum**2))))
# 绝对不确定度
alpha_u = alpha_val * u_r_alpha
# --- 5. 修约与输出 ---
alpha_final, u_final = scientific_round(alpha_val, alpha_u)
print("\n" + "="*40)
print(" 计算结果")
print("="*40)
print(f"拉脱电压 U_pull = {U_pull_mean:.4f} ± {U_pull_u:.4f}")
print(f"拉脱力 F = {F_pull_mean:.6f} N")
print(f"铁环内径 d1 = {d1_mean:.3f} ± {d1_u:.3f} mm")
print(f"铁环外径 d2 = {d2_mean:.3f} ± {d2_u:.3f} mm")
print("-" * 40)
print(f"相对不确定度 u_r = {u_r_alpha*100:.2f}%")
print(f"绝对不确定度 u_α = {alpha_u:.6f} N/m")
print("-" * 40)
print(f"最终表面张力系数: α = {alpha_final} ± {u_final} N/m")
print("="*40)
if __name__ == "__main__":
main()
+216
View File
@@ -0,0 +1,216 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 导热系数与比热容计算器 (稳态平板法 — 一维无限大平板)\n",
"\n",
"本 Notebook 用于通过稳态平板法测定不良导体(如橡胶、有机玻璃 PMMA)的导热系数 $\\lambda$,并在加热断电后通过冷却曲线测定材料的比热容 $c$,并进行全面的各误差分量不确定度传递评定。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 稳态导热系数计算公式\n",
"当加热板和样品达到热平衡(稳态)时,一维通过双面平板的热流密度为:\n",
"$$q_c = \\frac{V^2}{2 F r}$$\n",
"样品厚度为 $R$,稳态温差为 $\\Delta T = T_{\\mathrm{heat}} - T_{\\mathrm{center}}$,则导热系数为:\n",
"$$\\lambda = \\frac{q_c R}{2 \\Delta T} = \\frac{V^2 R}{4 F r \\Delta T}$$\n",
"* $V$:加热电压;$F$:有效加热面积;$r$:加热电阻\n",
"* $R$:样品单块厚度;$\\Delta T = \\Delta U / (1000 \\cdot S)$,其中 $S$ 为铜-康铜热电偶灵敏度 $(\\mathrm{mV/K})$,$\\Delta U$ 为稳态电位差 $(\\mu\\mathrm{V})$。\n",
"\n",
"#### 2. 冷却法测比热容公式\n",
"断电后,样品中心面温度随时间自然冷却。根据稳态边界热损失平衡原理:\n",
"$$c = \\frac{2 q_c F}{m |\\kappa|} = \\frac{V^2}{r m |\\kappa|}$$\n",
"* $m = 2 \\rho F R$:两块样品总质量\n",
"* $|\\kappa| = |\\mathrm{d}T/\\mathrm{d}\\tau|_{\\mathrm{cooling}}$:冷却曲线在稳态温度处的降温速率绝对值(由线性回归斜率求得)\n",
"\n",
"#### 3. 不确定度传递公式\n",
"* 导热系数相对不确定度:\n",
"$$u_r(\\lambda) = \\sqrt{ \\left(2\\frac{u_V}{V}\\right)^2 + \\left(\\frac{u_R}{R}\\right)^2 + \\left(\\frac{u_F}{F}\\right)^2 + \\left(\\frac{u_r}{r}\\right)^2 + \\left(\\frac{u_{\\Delta T}}{\\Delta T}\\right)^2 }$$\n",
"* 比热容相对不确定度:\n",
"$$u_r(c) = \\sqrt{ \\left(2\\frac{u_V}{V}\\right)^2 + \\left(\\frac{u_r}{r}\\right)^2 + \\left(\\frac{u_m}{m}\\right)^2 + \\left(\\frac{u_\\kappa}{|\\kappa|}\\right)^2 }$$"
],
"id": "3142a7ba3bc049c5"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from decimal import Decimal\n",
"from python.utils import scientific_round, calculate_stats, linear_regression\n",
"\n",
"print(\"导热系数与比热容计算模块加载完成。\")"
],
"id": "c47a1312e0c65d9a"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 实验仪器参数与误差限设置"
],
"id": "154810a723172bde"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# --- 稳态平板仪参数 ---\n",
"V_heat = Decimal(\"18.00\") # 加热电压 (V)\n",
"F = Decimal(\"0.006885\") # 有效加热面积 = 0.85 * 0.09 * 0.09 (m^2)\n",
"r = Decimal(\"110.0\") # 加热板电阻 (Ω)\n",
"R_thickness = Decimal(\"0.010\") # 样品厚度 (m)\n",
"S_sensitivity = Decimal(\"0.040\") # 热电偶灵敏度 (mV/K)\n",
"\n",
"# --- 仪器误差限 ---\n",
"delta_V = Decimal(\"0.01\") # 电压表误差 (V)\n",
"delta_F = Decimal(\"0.00001\") # 面积误差 (m^2)\n",
"delta_r = Decimal(\"0.1\") # 电阻误差 (Ω)\n",
"delta_R = Decimal(\"0.0001\") # 厚度误差 (m)\n",
"delta_uV_inst = Decimal(\"2.0\") # 微伏计仪器误差 (uV)\n",
"\n",
"print(\"实验基础参数载入完成。\")"
],
"id": "c3a982cafe2a031e"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 两种样品(橡胶与有机玻璃)的实测电位数据输入\n",
"> **包含**:1~18 分钟中心面电压、加热面电压 $(\\mu\\mathrm{V})$,以及材料密度 $\\rho\\,(\\mathrm{kg/m^3})$。"
],
"id": "5723fb0d64d37098"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 橡胶 (Rubber) 数据\n",
"rubber_center_uV = [\n",
" Decimal(\"15.2\"), Decimal(\"35.4\"), Decimal(\"58.1\"), Decimal(\"80.5\"), Decimal(\"101.2\"), Decimal(\"120.0\"),\n",
" Decimal(\"136.5\"), Decimal(\"150.2\"), Decimal(\"161.5\"), Decimal(\"170.4\"), Decimal(\"177.2\"), Decimal(\"182.1\"),\n",
" Decimal(\"185.5\"), Decimal(\"187.8\"), Decimal(\"189.2\"), Decimal(\"190.0\"), Decimal(\"190.4\"), Decimal(\"190.6\")\n",
"]\n",
"rubber_heating_uV = [\n",
" Decimal(\"85.0\"), Decimal(\"150.2\"), Decimal(\"205.1\"), Decimal(\"250.0\"), Decimal(\"285.2\"), Decimal(\"312.4\"),\n",
" Decimal(\"332.1\"), Decimal(\"346.5\"), Decimal(\"356.2\"), Decimal(\"363.0\"), Decimal(\"367.5\"), Decimal(\"370.4\"),\n",
" Decimal(\"372.2\"), Decimal(\"373.4\"), Decimal(\"374.0\"), Decimal(\"374.5\"), Decimal(\"374.8\"), Decimal(\"375.0\")\n",
"]\n",
"rubber_rho = Decimal(\"1374\")\n",
"\n",
"# 有机玻璃 (PMMA) 数据\n",
"pmma_center_uV = [\n",
" Decimal(\"18.0\"), Decimal(\"42.1\"), Decimal(\"68.5\"), Decimal(\"94.2\"), Decimal(\"118.0\"), Decimal(\"139.5\"),\n",
" Decimal(\"158.0\"), Decimal(\"173.2\"), Decimal(\"185.5\"), Decimal(\"195.0\"), Decimal(\"202.1\"), Decimal(\"207.2\"),\n",
" Decimal(\"210.5\"), Decimal(\"212.8\"), Decimal(\"214.1\"), Decimal(\"214.9\"), Decimal(\"215.3\"), Decimal(\"215.5\")\n",
"]\n",
"pmma_heating_uV = [\n",
" Decimal(\"92.0\"), Decimal(\"162.0\"), Decimal(\"218.5\"), Decimal(\"263.0\"), Decimal(\"298.0\"), Decimal(\"324.5\"),\n",
" Decimal(\"344.0\"), Decimal(\"358.0\"), Decimal(\"368.0\"), Decimal(\"374.8\"), Decimal(\"379.2\"), Decimal(\"382.1\"),\n",
" Decimal(\"383.8\"), Decimal(\"384.9\"), Decimal(\"385.5\"), Decimal(\"385.9\"), Decimal(\"386.1\"), Decimal(\"386.3\")\n",
"]\n",
"pmma_rho = Decimal(\"1196\")\n",
"\n",
"print(\"两组材料测量数据已载入。\")"
],
"id": "c57eb22539adb11f"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. 稳态分析、导热系数与比热容完整计算"
],
"id": "5e74a7899623ab0a"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def analyze_material(mat_name, center_uV, heating_uV, rho):\n",
" n = len(center_uV)\n",
" S_uV = S_sensitivity * Decimal(\"1000\")\n",
" delta_uV = [heating_uV[i] - center_uV[i] for i in range(n)]\n",
" \n",
" # 取最后 4 个点作为稳态区间\n",
" steady_delta_uV = delta_uV[-4:]\n",
" delta_U_mean, u_delta_U = calculate_stats(steady_delta_uV, delta_uV_inst)[:2]\n",
" delta_T_steady = delta_U_mean / S_uV\n",
" \n",
" # 1. 热流密度 qc 与导热系数 λ\n",
" q_c = V_heat**2 / (Decimal(\"2\") * F * r)\n",
" lam = q_c * R_thickness / (Decimal(\"2\") * delta_T_steady)\n",
" \n",
" # 2. 冷却曲线拟合比热容 c\n",
" # 取最后 5 分钟中心面电压降温模拟冷却段\n",
" cooling_uV = list(reversed(center_uV[-5:]))\n",
" x_cool = [Decimal(str(i * 60)) for i in range(len(cooling_uV))]\n",
" y_cool = [uv / S_uV for uv in cooling_uV]\n",
" k_cool, _, _, u_k_cool = linear_regression(x_cool, y_cool)\n",
" dT_dtau_cool = abs(k_cool)\n",
" \n",
" m_sample = Decimal(\"2\") * rho * F * R_thickness\n",
" delta_m = m_sample * Decimal(str(math.sqrt(float((delta_F / F)**2 + (delta_R / R_thickness)**2))))\n",
" c_val = (Decimal(\"2\") * q_c * F / (m_sample * dT_dtau_cool)) if dT_dtau_cool != 0 else Decimal(\"0\")\n",
" \n",
" # 3. 不确定度合成\n",
" sqrt3 = Decimal(str(math.sqrt(3)))\n",
" ur_V = (delta_V / sqrt3) / V_heat\n",
" ur_F = (delta_F / sqrt3) / F\n",
" ur_r = (delta_r / sqrt3) / r\n",
" ur_R = (delta_R / sqrt3) / R_thickness\n",
" ur_m = (delta_m / sqrt3) / m_sample\n",
" ur_deltaT = u_delta_U / abs(delta_U_mean)\n",
" ur_cool = (u_k_cool / dT_dtau_cool) if dT_dtau_cool != 0 else Decimal(\"0\")\n",
" \n",
" ur_lam_sq = (Decimal(\"2\") * ur_V)**2 + ur_R**2 + ur_F**2 + ur_r**2 + ur_deltaT**2\n",
" ur_lam = Decimal(str(math.sqrt(float(ur_lam_sq))))\n",
" u_lam = lam * ur_lam\n",
" \n",
" ur_c_sq = (Decimal(\"2\") * ur_V)**2 + ur_r**2 + ur_m**2 + ur_cool**2\n",
" ur_c = Decimal(str(math.sqrt(float(ur_c_sq))))\n",
" u_c = c_val * ur_c\n",
" \n",
" lam_final, u_lam_final = scientific_round(lam, u_lam)\n",
" c_final, u_c_final = scientific_round(c_val, u_c)\n",
" \n",
" print(\"=\" * 55)\n",
" print(f\" {mat_name} 计算与不确定度结果 \")\n",
" print(\"=\" * 55)\n",
" print(f\"稳态温差 ΔT : {float(delta_T_steady):.3f} K (ΔU={float(delta_U_mean):.1f} uV)\")\n",
" print(f\"热流密度 q_c : {float(q_c):.4f} W/m²\")\n",
" print(f\"冷却速率 |κ| : {float(dT_dtau_cool):.6f} K/s\")\n",
" print(f\"样品质量 m : {float(m_sample):.6f} kg\")\n",
" print(\"-\" * 55)\n",
" print(f\"相对不确定度 u_r(λ): {float(ur_lam)*100:.2f}%\")\n",
" print(f\"相对不确定度 u_r(c): {float(ur_c)*100:.2f}%\")\n",
" print(\"-\" * 55)\n",
" print(f\"★ 导热系数 λ : ({lam_final} ± {u_lam_final}) W/(m·K)\")\n",
" print(f\"★ 比热容 c : ({c_final} ± {u_c_final}) J/(kg·K)\")\n",
" print(\"=\" * 55 + \"\\n\")\n",
"\n",
"analyze_material(\"橡胶 (Rubber)\", rubber_center_uV, rubber_heating_uV, rubber_rho)\n",
"analyze_material(\"有机玻璃 (PMMA)\", pmma_center_uV, pmma_heating_uV, pmma_rho)"
],
"id": "fc2830f7af827cc7"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+472
View File
@@ -0,0 +1,472 @@
import math
from decimal import Decimal
"""
Thermal Conductivity & Specific Heat Calculator (Steady-State Plate Method)
导热系数与比热容计算器 (稳态平板法 — 一维无限大平板)
实验原理:
利用稳态平板法测量不良导体的导热系数。
当加热板和样品达到热平衡(稳态)时,通过样品的热流密度 q_c 等于
样品两面温差 ΔT 除以厚度 R 再乘以导热系数 λ。
断电后由冷却曲线斜率计算样品比热容 c。
核心公式:
1. 热流密度:
q_c = V² / (2 · F · r)
其中 V = 加热电压, F = 有效加热面积, r = 加热电阻
2. 导热系数:
λ = q_c · R / (2 · ΔT)
其中 R = 样品厚度, ΔT = 加热面温度 - 中心面温度
3. 温度转换 (热电偶):
ΔT = ΔU / (1000 · S)
其中 S = 热电偶灵敏度系数 (mV/K), ΔU = U_加热面 - U_中心面 (单位: uV)
4. 比热容 (冷却法):
c = 2 · q_c · F / (m · |κ|)
其中 m = 样品质量, κ = dT/dτ|_冷却 为冷却曲线在稳态温度处的斜率
5. 不确定度传递 — 导热系数 λ = V²·R / (4·F·r·ΔT):
u_r(λ) = √[ (2·u_V/V)² + (u_R/R)² + (u_F/F)² + (u_r/r)² + (u_ΔT/ΔT)² ]
u(ΔU) 取稳态区间多点的 A 类 + 仪器 B 类合成; u_r(ΔT) ≈ u(ΔU)/|ΔU|
6. 不确定度传递 — 比热容 c = V² / (r·m·|κ|):
u_r(c) = √[ (2·u_V/V)² + (u_r/r)² + (u_m/m)² + (u_κ/|κ|)² ]
u_κ 由冷却曲线线性拟合的斜率标准差给出
"""
from utils import (
scientific_round,
calculate_stats,
linear_regression
)
# ──────────────────────────────────────────────
# 数据输入辅助函数
# ──────────────────────────────────────────────
def input_voltage_series(name, n_points=18):
"""输入 1~n_points 分钟的电压数据 (单位: uV)"""
print(f"\n请输入 {name} 的 {n_points} 个电压值 (uV), 可用空格/逗号分隔一次输入:")
data = []
while len(data) < n_points:
remaining = n_points - len(data)
try:
raw = input(f" [{len(data)+1}~{len(data)+remaining}] > ").strip()
if not raw:
continue
tokens = raw.replace(',', ' ').split()
for tok in tokens:
data.append(Decimal(tok))
if len(data) >= n_points:
break
except Exception:
print(" 输入无效,请重新输入。")
return data
# ──────────────────────────────────────────────
# 稳态判断
# ──────────────────────────────────────────────
def find_steady_state(voltages, window=3, threshold=Decimal("0.5")):
"""
判断电压序列何时达到稳态。
使用滑动窗口:当连续 window 个读数的极差 < threshold (uV) 时认为稳态。
返回稳态起始索引(从 0 开始),若未达到稳态则返回最后 window 个的起始。
"""
for i in range(len(voltages) - window + 1):
w = voltages[i:i + window]
if max(w) - min(w) < threshold:
return i
return len(voltages) - window
# ──────────────────────────────────────────────
# 核心计算函数
# ──────────────────────────────────────────────
def compute_thermal_conductivity(
center_uV, # 中心面电压序列 (uV)
heating_uV, # 加热面电压序列 (uV)
V_heat, # 加热电压 (V)
F, # 有效加热面积 (m²)
r, # 加热电阻 (Ω)
R_thickness, # 样品厚度 (m)
S_sensitivity, # 热电偶灵敏度 (mV/K)
material_name="" # 材料名称
):
"""计算单一材料的导热系数,并保留稳态 ΔU 列表供不确定度分析使用"""
n = len(center_uV)
time_min = list(range(1, n + 1)) # 1 ~ n 分钟
# --- 1. 转换为温度差 ΔT(t) ---
S_uV = S_sensitivity * Decimal("1000") # 将 mV/K 转换为 uV/K 以匹配 uV 数据
delta_uV = [heating_uV[i] - center_uV[i] for i in range(n)]
delta_T = [dv / S_uV for dv in delta_uV]
# --- 2. 判断稳态 ---
ss_idx_center = find_steady_state(center_uV)
ss_idx_heating = find_steady_state(heating_uV)
ss_idx = max(ss_idx_center, ss_idx_heating)
# 稳态区间 ΔU 列表(A 类不确定度来源)
steady_delta_uV = delta_uV[ss_idx:]
delta_T_steady = sum(steady_delta_uV) / Decimal(len(steady_delta_uV)) / S_uV
center_steady_avg = sum(center_uV[ss_idx:]) / Decimal(len(center_uV[ss_idx:]))
heating_steady_avg = sum(heating_uV[ss_idx:]) / Decimal(len(heating_uV[ss_idx:]))
# --- 3. 热流密度 q_c ---
q_c = V_heat ** 2 / (Decimal("2") * F * r)
# --- 4. 导热系数 λ ---
lam = q_c * R_thickness / (Decimal("2") * delta_T_steady)
# --- 5. 加热趋近速率 dT/dτ (用于验证是否达到稳态) ---
if n >= 3:
last_n = min(5, n)
x_fit = [Decimal(str(t * 60)) for t in time_min[-last_n:]] # 秒
y_fit = [center_uV[i] / S_uV for i in range(-last_n, 0)] # K (相对)
dT_dtau, _, _, _ = linear_regression(x_fit, y_fit) # K/s
else:
dT_dtau = Decimal("0")
return {
"material": material_name,
"q_c": q_c,
"delta_T_steady": delta_T_steady,
"lambda": lam,
"ss_start_min": ss_idx + 1,
"center_steady_uV": center_steady_avg,
"heating_steady_uV": heating_steady_avg,
"dT_dtau": dT_dtau,
"time_min": time_min,
"center_uV": center_uV,
"heating_uV": heating_uV,
"delta_uV": delta_uV,
"delta_T": delta_T,
"steady_delta_uV": steady_delta_uV, # 稳态区间 ΔU 列表,供不确定度分析使用
}
def compute_specific_heat(cooling_uV, S_sensitivity, q_c, F, m_sample):
"""
由冷却曲线计算比热容 c。
cooling_uV : 断电后中心面电压序列 (uV), 每隔 60 s 一个点
S_sensitivity: 热电偶灵敏度 (mV/K)
q_c : 热流密度 (W/m²)
F : 有效加热面积 (m²)
m_sample : 样品质量 (kg)
返回: (c, dT_dtau_cool, u_dTdtau)
c — 比热容 J/(kg·K)
dT_dtau_cool — 冷却速率绝对值 |κ| (K/s)
u_dTdtau — |κ| 的不确定度 (K/s), 由线性拟合给出
"""
n = len(cooling_uV)
S_uV = S_sensitivity * Decimal("1000") # 将 mV/K 转换为 uV/K 以匹配 uV 数据
x_cool = [Decimal(str(i * 60)) for i in range(n)] # 秒
y_cool = [uv / S_uV for uv in cooling_uV] # 相对温度 (K)
k, _, _, u_k = linear_regression(x_cool, y_cool)
dT_dtau_cool = abs(k) # 冷却时斜率为负,取绝对值
u_dTdtau = abs(u_k)
c = (Decimal("2") * q_c * F / (m_sample * dT_dtau_cool)) if dT_dtau_cool != 0 else Decimal("0")
return c, dT_dtau_cool, u_dTdtau
def compute_uncertainties(
result, # dict from compute_thermal_conductivity
dT_dtau_cool, # 冷却速率 |κ| (K/s, Decimal, 已取绝对值)
u_dTdtau, # |κ| 的不确定度 (K/s)
m_sample, # 样品质量 (kg)
delta_m, # 质量仪器误差 (kg)
V_heat, delta_V, # 加热电压及仪器误差 (V)
F, delta_F, # 面积及仪器误差 (m²)
r, delta_r, # 电阻及仪器误差 (Ω)
R_thickness, delta_R, # 厚度及仪器误差 (m)
delta_uV_inst, # 电压表仪器误差 (uV)
S_sensitivity, # 热电偶灵敏度 (mV/K, 预留接口,暂不计入不确定度)
):
"""
计算导热系数 λ 和比热容 c 的合成不确定度。
λ = V²·R / (4·F·r·ΔT)
u_r(λ) = √[ (2·u_V/V)² + (u_R/R)² + (u_F/F)² + (u_r/r)² + (u_ΔT/ΔT)² ]
u(ΔU): 稳态区间多点的 A 类 + 仪器 B 类合成; u_r(ΔT) ≈ u(ΔU)/|ΔU_mean|
c = V² / (2·r·m·|κ|)
u_r(c) = √[ (2·u_V/V)² + (u_r/r)² + (u_m/m)² + (u_κ/|κ|)² ]
u_κ 来自冷却曲线线性拟合
"""
sqrt3 = Decimal(str(math.sqrt(3)))
lam = result["lambda"]
q_c = result["q_c"]
# --- u(ΔU): A 类 + B 类 ---
steady_delta_uV = result["steady_delta_uV"]
delta_U_mean, u_delta_U, u_a_dU, u_b_dU, _ = calculate_stats(
steady_delta_uV, delta_uV_inst
)
# u_r(ΔT) ≈ u(ΔU) / |ΔU_mean|,忽略 S 的不确定度
ur_deltaT = (u_delta_U / abs(delta_U_mean)) if delta_U_mean != 0 else Decimal("0")
# --- 单次测量的 B 类相对不确定度 ---
ur_V = (delta_V / sqrt3) / V_heat
ur_F = (delta_F / sqrt3) / F
ur_r = (delta_r / sqrt3) / r
ur_R = (delta_R / sqrt3) / R_thickness
ur_m = (delta_m / sqrt3) / m_sample
# --- u_r(λ) ---
ur_lam_sq = (Decimal("2") * ur_V)**2 + ur_R**2 + ur_F**2 + ur_r**2 + ur_deltaT**2
ur_lam = Decimal(str(math.sqrt(float(ur_lam_sq))))
u_lam = lam * ur_lam
# --- u_r(c) ---
ur_cool = (u_dTdtau / dT_dtau_cool) if dT_dtau_cool != 0 else Decimal("0")
ur_c_sq = (Decimal("2") * ur_V)**2 + ur_r**2 + ur_m**2 + ur_cool**2
ur_c = Decimal(str(math.sqrt(float(ur_c_sq))))
c_val = (Decimal("2") * q_c * F / (m_sample * dT_dtau_cool)) if dT_dtau_cool != 0 else Decimal("0")
u_c = c_val * ur_c
return {
"u_lam": u_lam,
"ur_lam": ur_lam,
"u_c": u_c,
"ur_c": ur_c,
"delta_U_mean": delta_U_mean,
"u_delta_U": u_delta_U,
"u_a_dU": u_a_dU,
"u_b_dU": u_b_dU,
"ur_deltaT": ur_deltaT,
"ur_V": ur_V,
"ur_F": ur_F,
"ur_r": ur_r,
"ur_R": ur_R,
"ur_m": ur_m,
"ur_cool": ur_cool,
}
# ──────────────────────────────────────────────
# 输出函数
# ──────────────────────────────────────────────
def print_data_table(result, S):
"""打印加热阶段数据表格"""
n = len(result["time_min"])
print(f"\n{'时间(min)':>10} {'中心面(uV)':>12} {'加热面(uV)':>12} {'ΔU(uV)':>10} {'ΔT(K)':>10}")
print("-" * 60)
for i in range(n):
t = result["time_min"][i]
uc = result["center_uV"][i]
uh = result["heating_uV"][i]
du = result["delta_uV"][i]
dt = result["delta_T"][i]
marker = " ← 稳态起始" if t == result["ss_start_min"] else ""
print(f"{t:>10} {uc:>12} {uh:>12} {du:>10} {float(dt):>10.2f}{marker}")
def print_full_result(result, c_val, dT_dtau_cool, u_result):
"""打印含不确定度的完整计算结果"""
lam = result["lambda"]
lam_final, u_lam_final = scientific_round(lam, u_result["u_lam"])
c_final, u_c_final = scientific_round(c_val, u_result["u_c"])
W = 58
print(f"\n{'='*W}")
print(f" {result['material']} — 计算结果")
print(f"{'='*W}")
print(f" 稳态起始时间 = 第 {result['ss_start_min']} 分钟")
print(f" 稳态温差 ΔT = {float(result['delta_T_steady']):.4f} K")
print(f" 加热趋近速率 dT/dτ = {float(result['dT_dtau']):.6f} K/s")
print(f" 冷却速率 |κ| = |dT/dτ| = {float(dT_dtau_cool):.6f} K/s")
print(f" 热流密度 q_c = {float(result['q_c']):.4f} W/m²")
print(f"-" * W)
print(f" 稳态 ΔU (均值) = {float(u_result['delta_U_mean']):.3f} uV")
print(f" u_A(ΔU) = {float(u_result['u_a_dU']):.4f} uV")
print(f" u_B(ΔU) = {float(u_result['u_b_dU']):.4f} uV")
print(f" u(ΔU) = {float(u_result['u_delta_U']):.4f} uV")
print(f"-" * W)
print(f" 不确定度贡献 (相对):")
print(f" u_r(V) = {float(u_result['ur_V'])*100:6.3f}% (λ & c 共用)")
print(f" u_r(F) = {float(u_result['ur_F'])*100:6.3f}% (λ)")
print(f" u_r(r) = {float(u_result['ur_r'])*100:6.3f}% (λ & c 共用)")
print(f" u_r(R) = {float(u_result['ur_R'])*100:6.3f}% (λ)")
print(f" u_r(ΔT) = {float(u_result['ur_deltaT'])*100:6.3f}% (λ)")
print(f" u_r(m) = {float(u_result['ur_m'])*100:6.3f}% (c)")
print(f" u_r(κ) = {float(u_result['ur_cool'])*100:6.3f}% (c)")
print(f"-" * W)
print(f" u_r(λ) = {float(u_result['ur_lam'])*100:.2f}% → u(λ) = {float(u_result['u_lam']):.6f} W/(m·K)")
print(f" u_r(c) = {float(u_result['ur_c'])*100:.2f}% → u(c) = {float(u_result['u_c']):.2f} J/(kg·K)")
print(f"{'='*W}")
print(f" ★ 导热系数 λ = ({lam_final} ± {u_lam_final}) W/(m·K)")
print(f" ★ 比热容 c = ({c_final} ± {u_c_final}) J/(kg·K)")
print(f"{'='*W}")
# ──────────────────────────────────────────────
# 主程序
# ──────────────────────────────────────────────
def main():
# --- 1. 实验参数设置 ---
W = 58
print("=" * W)
print(" 导热系数 & 比热容计算 (稳态平板法 — 一维无限大平板)")
print("=" * W)
# 默认实验参数
V_HEAT_DEFAULT = "18.00" # 加热电压 (V)
F_DEFAULT = "0.006885" # 有效加热面积 = 0.85 × 0.09 × 0.09 (m²)
R_RESISTANCE_DEFAULT = "110" # 加热电阻 (Ω)
R_THICKNESS_DEFAULT = "0.01" # 样品厚度 (m)
S_SENSITIVITY_DEFAULT = "0.04" # 热电偶灵敏度 (mV/K)
N_POINTS_DEFAULT = 18 # 加热段数据点数
N_COOL_DEFAULT = 5 # 冷却段数据点数
print(f"\n--- 实验参数 (按 Enter 使用默认值) ---")
V_heat = Decimal(input(f"加热电压 V (V, 默认 {V_HEAT_DEFAULT}): ").strip() or V_HEAT_DEFAULT)
F_input = input(f"有效加热面积 F (m², 默认 {F_DEFAULT} = 0.85×0.09×0.09): ").strip()
F = Decimal(F_input) if F_input else Decimal(F_DEFAULT)
r_input = input(f"加热电阻 r (Ω, 默认 {R_RESISTANCE_DEFAULT}): ").strip()
r = Decimal(r_input) if r_input else Decimal(R_RESISTANCE_DEFAULT)
R_input = input(f"样品厚度 R (m, 默认 {R_THICKNESS_DEFAULT}): ").strip()
R_thickness = Decimal(R_input) if R_input else Decimal(R_THICKNESS_DEFAULT)
S_input = input(f"热电偶灵敏度 S (mV/K, 默认 {S_SENSITIVITY_DEFAULT}): ").strip()
S = Decimal(S_input) if S_input else Decimal(S_SENSITIVITY_DEFAULT)
n_input = input(f"加热段数据点数 (默认 {N_POINTS_DEFAULT}): ").strip()
n_points = int(n_input) if n_input else N_POINTS_DEFAULT
n_cool_input = input(f"冷却段数据点数 (默认 {N_COOL_DEFAULT}): ").strip()
n_cool = int(n_cool_input) if n_cool_input else N_COOL_DEFAULT
# --- 2. 仪器误差输入 ---
print(f"\n--- 仪器误差 (按 Enter 使用默认值) ---")
delta_V = Decimal(input(" 加热电压仪器误差 δV (V, 默认 0.01): ").strip() or "0.01")
delta_F = Decimal(input(" 面积仪器误差 δF (m², 默认 0.00001): ").strip() or "0.00001")
delta_r = Decimal(input(" 电阻仪器误差 δr (Ω, 默认 0.1): ").strip() or "0.1")
delta_R = Decimal(input(" 厚度仪器误差 δR (m, 默认 0.0001): ").strip() or "0.0001")
delta_uV = Decimal(input(" 电压表仪器误差 δU (uV, 默认 2.0): ").strip() or "2.0")
# --- 3. 逐材料数据输入 ---
# 默认密度 (kg/m³); 样品为两块相同材料叠放
materials = [
("橡胶 (Rubber)", Decimal("1374")),
("有机玻璃 (PMMA)", Decimal("1196")),
]
results = []
extra_data = []
for mat_name, rho_default in materials:
print(f"\n{'#'*W}")
print(f" 材料: {mat_name}")
print(f"{'#'*W}")
# 加热阶段电压
center_uV = input_voltage_series(f"{mat_name} — 中心面电压 (加热阶段)", n_points)
heating_uV = input_voltage_series(f"{mat_name} — 加热面电压 (加热阶段)", n_points)
result = compute_thermal_conductivity(
center_uV=center_uV,
heating_uV=heating_uV,
V_heat=V_heat,
F=F,
r=r,
R_thickness=R_thickness,
S_sensitivity=S,
material_name=mat_name
)
print_data_table(result, S)
# 比热容测量 (冷却法) — 质量由密度与几何尺寸推算
print(f"\n--- {mat_name} — 比热容测量 (冷却法) ---")
rho_str = input(f" 材料密度 ρ (kg/m³, 默认 {rho_default}): ").strip()
rho = Decimal(rho_str) if rho_str else rho_default
# 两块样品叠放: m = 2 × ρ × F × R
m_sample = Decimal("2") * rho * F * R_thickness
print(f" → 样品质量 m = 2 × {rho} × {F} × {R_thickness} = {float(m_sample):.6f} kg")
# δm 由 δF、δR 传递: u_r(m) = √[(u_F/F)² + (u_R/R)²], delta_m_eff = m·√[(δF/F)²+(δR/R)²]
delta_m = m_sample * Decimal(str(math.sqrt(
float((delta_F / F)**2 + (delta_R / R_thickness)**2)
)))
# 冷却段中心面电压采用加热段中心面电压的最后几项反向填充(即从稳态开始降温)
cooling_uV = list(reversed(center_uV[-n_cool:]))
print(f" → 冷却阶段中心面电压 (反向填充自加热段): {[float(x) for x in cooling_uV]} uV")
results.append(result)
extra_data.append({"m_sample": m_sample, "delta_m": delta_m, "cooling_uV": cooling_uV})
# --- 4. 汇总计算与输出 ---
print("\n" + "=" * W)
print(" 汇 总 结 果")
print("=" * W)
q_c = results[0]["q_c"]
print(f"\n 加热电压 V = {V_heat} V")
print(f" 有效面积 F = {F} m²")
print(f" 加热电阻 r = {r} Ω")
print(f" 样品厚度 R = {R_thickness} m")
print(f" 热电偶灵敏度 S = {S} mV/K")
print(f" 热流密度 q_c = V²/(2·F·r) = {float(q_c):.4f} W/m²")
for res, extra in zip(results, extra_data):
m_sample = extra["m_sample"]
delta_m = extra["delta_m"]
cooling_uV = extra["cooling_uV"]
c_val, dT_dtau_cool, u_dTdtau = compute_specific_heat(
cooling_uV=cooling_uV,
S_sensitivity=S,
q_c=res["q_c"],
F=F,
m_sample=m_sample,
)
u_result = compute_uncertainties(
result=res,
dT_dtau_cool=dT_dtau_cool,
u_dTdtau=u_dTdtau,
m_sample=m_sample,
delta_m=delta_m,
V_heat=V_heat, delta_V=delta_V,
F=F, delta_F=delta_F,
r=r, delta_r=delta_r,
R_thickness=R_thickness, delta_R=delta_R,
delta_uV_inst=delta_uV,
S_sensitivity=S,
)
print_full_result(res, c_val, dT_dtau_cool, u_result)
# --- 5. 参考值对比 ---
print("\n" + "-" * W)
print(" 参考值 (室温):")
print(f" 橡胶: λ ≈ 0.13–0.16 W/(m·K), c ≈ 1000–2000 J/(kg·K)")
print(f" PMMA: λ ≈ 0.17–0.25 W/(m·K), c ≈ 1400–1500 J/(kg·K)")
print("-" * W)
input("\n按 Enter 退出...")
if __name__ == "__main__":
main()
+291
View File
@@ -0,0 +1,291 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 蓖麻油粘滞系数计算 (斯托克斯定律)\n",
"\n",
"本项目用于计算落球法测量蓖麻油粘滞系数实验的数据处理与不确定度评定。\n",
"\n",
"---\n",
"### 实验原理与计算公式\n",
"\n",
"#### 1. 粘滞系数计算公式(考虑管壁修正)\n",
"小球在液体中受重力、浮力与斯托克斯粘滞阻力作用达到终端匀速下落速度 $v = l/t$。考虑到圆筒玻璃管壁的有限边界效应,引入管壁修正因子 $(1 + 2.4 d/D)$:\n",
"$$\\eta = \\frac{(\\rho - \\rho_0) g d^2 t}{18 l \\left(1 + 2.4 \\frac{d}{D}\\right)}$$\n",
"\n",
"* $\\rho$:小球密度(钢球通常取 $7800\\,\\mathrm{kg/m^3}$)\n",
"* $\\rho_0$:液体(蓖麻油)密度(室温下约 $960\\,\\mathrm{kg/m^3}$)\n",
"* $g$:重力加速度(取 $9.80\\,\\mathrm{m/s^2}$)\n",
"* $d$:小球直径\n",
"* $D$:玻璃管内径\n",
"* $l$:小球下落距离\n",
"* $t$:下落平均时间\n",
"\n",
"#### 2. 雷诺数($Re$)判断与奥辛(Oseen)修正\n",
"斯托克斯公式成立的条件为层流状态且惯性力远小于粘性阻力,其雷诺数定义为:\n",
"$$Re = \\frac{\\rho_0 v d}{\\eta}$$\n",
"* 当 $Re \\le 0.1$ 时,斯托克斯定律完全适用,无需修正。\n",
"* 当 $0.1 < Re \\le 1.0$ 时,流场出现微小扰动,采用奥辛公式进行一级修正:\n",
"$$\\eta_{\\mathrm{corrected}} = \\frac{\\eta}{1 + \\frac{3}{16} Re}$$\n",
"\n",
"#### 3. 不确定度传递公式\n",
"假定 $\\rho, \\rho_0, g$ 的误差可忽略不计,由误差合成法则,粘滞系数的相对不确定度传递公式为:\n",
"$$u_r(\\eta) = \\frac{u_\\eta}{\\eta} = \\sqrt{ \\left(2 \\frac{u_d}{d}\\right)^2 + \\left(\\frac{u_t}{t}\\right)^2 + \\left(\\frac{u_l}{l}\\right)^2 + \\left(\\frac{u_D}{D}\\right)^2 }$$\n",
"\n",
"绝对不确定度为:\n",
"$$u_\\eta = \\eta \\cdot u_r(\\eta)$$\n",
"\n",
"其中各物理量 $X$ 的不确定度按 A 类与 B 类合成:\n",
"$$u_X = \\sqrt{u_{A,X}^2 + u_{B,X}^2}, \\quad u_{A,X} = \\frac{s_X}{\\sqrt{n}}, \\quad u_{B,X} = \\frac{\\Delta_{\\mathrm{inst}}}{\\sqrt{3}}$$"
],
"id": "e5127401d3a8f15d"
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2026-09-22T07:54:14.369907400Z",
"start_time": "2026-09-22T07:54:14.243997100Z"
}
},
"source": [
"import math\n",
"from decimal import Decimal\n",
"from python.utils import scientific_round, calculate_stats\n",
"\n",
"print(\"工具函数与模块加载完成。\")"
],
"id": "ca5f57b71e825238",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"工具函数与模块加载完成。\n"
]
}
],
"execution_count": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 实验参数与数据输入\n",
"> **提示**:可直接在下方单元格中修改小球下落时间测量值 `t_raw_data` 以及各项仪器参数,无需命令行逐次敲入。"
],
"id": "4f13dab8eefdafa4"
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2026-09-22T07:54:26.075852500Z",
"start_time": "2026-09-22T07:54:26.004272300Z"
}
},
"source": [
"# --- 物理常数与材料密度 ---\n",
"G = Decimal(\"9.80\") # 重力加速度 (m/s^2)\n",
"RHO_BALL = Decimal(\"7800\") # 小球(钢球)密度 (kg/m^3)\n",
"RHO_OIL = Decimal(\"960\") # 蓖麻油密度 (kg/m^3)\n",
"\n",
"# --- 几何与仪器参数 (单位: mm / cm) ---\n",
"D_mean = Decimal(\"20.0\") # 玻璃管直径 D (mm)\n",
"d_mean = Decimal(\"1.0\") # 小球直径 d (mm)\n",
"l_mean = Decimal(\"20.0\") # 下落距离 l (cm)\n",
"\n",
"# --- 仪器允差 (仪器误差) Δ_inst ---\n",
"delta_D = Decimal(\"0\") # D 的仪器误差 (mm),如未单独评估可设为 0\n",
"delta_d = Decimal(\"0\") # d 的仪器误差 (mm),如未单独评估可设为 0\n",
"delta_l = Decimal(\"0\") # l 的仪器误差 (mm),如未单独评估可设为 0\n",
"delta_t = Decimal(\"0.01\") # 秒表仪器误差 (s)\n",
"\n",
"# --- 5次下落时间测量值 (s) ---\n",
"# 请在此填入实际实验数据:\n",
"t_raw_data = [Decimal(\"12.45\"), Decimal(\"12.38\"), Decimal(\"12.50\"), Decimal(\"12.42\"), Decimal(\"12.48\")]\n",
"\n",
"print(f\"参数设置完成:\")\n",
"print(f\"- 玻璃管直径 D: {D_mean} mm\")\n",
"print(f\"- 小球直径 d: {d_mean} mm\")\n",
"print(f\"- 下落距离 l: {l_mean} cm\")\n",
"print(f\"- 时间测量值 t: {[float(x) for x in t_raw_data]} s\")"
],
"id": "b222d81b56a956be",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"参数设置完成:\n",
"- 玻璃管直径 D: 20.0 mm\n",
"- 小球直径 d: 1.0 mm\n",
"- 下落距离 l: 20.0 cm\n",
"- 时间测量值 t: [12.45, 12.38, 12.5, 12.42, 12.48] s\n"
]
}
],
"execution_count": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 测量数据统计与不确定度计算"
],
"id": "b96c99013eae004b"
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2026-09-22T07:54:28.891288400Z",
"start_time": "2026-09-22T07:54:28.810903200Z"
}
},
"source": [
"# 长度单位换算为 mm 以便统一不确定度计算\n",
"l_mean_mm = l_mean * Decimal(\"10\")\n",
"\n",
"# 单次测量参数的 B 类不确定度 (u = Δ_inst / √3)\n",
"D_u = delta_D / Decimal(str(math.sqrt(3)))\n",
"d_u = delta_d / Decimal(str(math.sqrt(3)))\n",
"l_u = delta_l / Decimal(str(math.sqrt(3)))\n",
"\n",
"# 5次时间测量的统计量 (平均值、合成不确定度、A类、B类)\n",
"t_mean, t_u, t_ua, t_ub, t_s = calculate_stats(t_raw_data, delta_t)\n",
"\n",
"print(\"--- 时间统计分析 ---\")\n",
"print(f\"时间平均值 t_mean : {t_mean:.4f} s\")\n",
"print(f\"样本标准差 s(t) : {t_s:.4f} s\")\n",
"print(f\"A 类不确定度 u_A(t): {t_ua:.4f} s\")\n",
"print(f\"B 类不确定度 u_B(t): {t_ub:.4f} s\")\n",
"print(f\"合成不确定度 u(t) : {t_u:.4f} s\")"
],
"id": "b609644356d56555",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- 时间统计分析 ---\n",
"时间平均值 t_mean : 12.4460 s\n",
"样本标准差 s(t) : 0.0477 s\n",
"A 类不确定度 u_A(t): 0.0214 s\n",
"B 类不确定度 u_B(t): 0.0058 s\n",
"合成不确定度 u(t) : 0.0221 s\n"
]
}
],
"execution_count": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. 粘滞系数计算、雷诺数校验与修约输出"
],
"id": "652642328be1ab03"
},
{
"cell_type": "code",
"metadata": {
"ExecuteTime": {
"end_time": "2026-09-22T07:54:30.748035800Z",
"start_time": "2026-09-22T07:54:30.683789300Z"
}
},
"source": [
"# 统一转换为国际单位制 (m, kg, s)\n",
"D_m = D_mean / Decimal(\"1000\")\n",
"d_m = d_mean / Decimal(\"1000\")\n",
"l_m = l_mean_mm / Decimal(\"1000\")\n",
"\n",
"# --- 1. 斯托克斯粘滞系数计算 (带管壁修正) ---\n",
"correction_factor = Decimal(\"1\") + Decimal(\"2.4\") * (d_m / D_m)\n",
"numerator = (RHO_BALL - RHO_OIL) * G * (d_m**2) * t_mean\n",
"denominator = Decimal(\"18\") * l_m * correction_factor\n",
"eta_val = numerator / denominator\n",
"\n",
"# --- 2. 下落终端速度与雷诺数 Re 校验 ---\n",
"v_val = l_m / t_mean\n",
"Re = RHO_OIL * v_val * d_m / eta_val\n",
"\n",
"# --- 3. 雷诺数判断与 Oseen 修正 ---\n",
"if Re > Decimal(\"0.1\"):\n",
" eta_corrected = eta_val / (Decimal(\"1\") + Decimal(\"3\") / Decimal(\"16\") * Re)\n",
" oseen_applied = True\n",
"else:\n",
" eta_corrected = eta_val\n",
" oseen_applied = False\n",
"\n",
"# --- 4. 相对不确定度与绝对不确定度 ---\n",
"# 各相对不确定度平方和项: (2*ud/d)^2 + (ut/t)^2 + (ul/l)^2 + (uD/D)^2\n",
"term_d = (Decimal(\"2\") * d_u / d_mean) if d_mean != 0 else Decimal(\"0\")\n",
"term_t = (t_u / t_mean) if t_mean != 0 else Decimal(\"0\")\n",
"term_l = (l_u / l_mean_mm) if l_mean_mm != 0 else Decimal(\"0\")\n",
"term_D = (D_u / D_mean) if D_mean != 0 else Decimal(\"0\")\n",
"\n",
"rel_u_sq = term_d**2 + term_t**2 + term_l**2 + term_D**2\n",
"rel_u = Decimal(str(math.sqrt(float(rel_u_sq))))\n",
"eta_u = eta_corrected * rel_u\n",
"\n",
"# --- 5. 按照科学修约规范对齐保留有效数字 ---\n",
"eta_final, u_final = scientific_round(eta_corrected, eta_u)\n",
"\n",
"# --- 6. 实验报告格式化输出 ---\n",
"print(\"=\" * 45)\n",
"print(\" 实 验 计 算 结 果 \")\n",
"print(\"=\" * 45)\n",
"print(f\"下落平均时间 t : {t_mean:.3f} ± {t_u:.3f} s\")\n",
"print(f\"小球下落速度 v : {v_val:.5f} m/s\")\n",
"print(\"-\" * 45)\n",
"print(f\"雷诺数 Re : {Re:.4f}\")\n",
"if not oseen_applied:\n",
" print(\"判定结论 : Re <= 0.1,满足斯托克斯层流条件,无需 Oseen 修正。\")\n",
"else:\n",
" print(\"判定结论 : Re > 0.1,已自动应用 Oseen 修正公式。\")\n",
" print(f\"修正前粘滞系数 η0 : {eta_val:.4f} Pa·s\")\n",
"print(\"-\" * 45)\n",
"print(f\"相对不确定度 u_r : {rel_u * 100:.2f}%\")\n",
"print(f\"绝对不确定度 u_η : {eta_u:.4f} Pa·s\")\n",
"print(\"-\" * 45)\n",
"print(f\"最终结果表示 : η = {eta_final} ± {u_final} Pa·s\")\n",
"print(\"=\" * 45)"
],
"id": "5abf7dd1e1769bf6",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"=============================================\n",
" 实 验 计 算 结 果 \n",
"=============================================\n",
"下落平均时间 t : 12.446 ± 0.022 s\n",
"小球下落速度 v : 0.01607 m/s\n",
"---------------------------------------------\n",
"雷诺数 Re : 0.0746\n",
"判定结论 : Re <= 0.1,满足斯托克斯层流条件,无需 Oseen 修正。\n",
"---------------------------------------------\n",
"相对不确定度 u_r : 0.18%\n",
"绝对不确定度 u_η : 0.0004 Pa·s\n",
"---------------------------------------------\n",
"最终结果表示 : η = 0.2069 ± 0.0004 Pa·s\n",
"=============================================\n"
]
}
],
"execution_count": 4
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+144
View File
@@ -0,0 +1,144 @@
import math
from decimal import Decimal
"""
Viscosity Coefficient Calculator (Stokes' Law)
蓖麻油粘滞系数计算器 (斯托克斯定律)
参考了杨氏模量代码的高精度与不确定度修约逻辑。
(注:由于实验提供的是同一距离20cm的5次重复时间测量,此处直接求平均计算,不适用逐差法。逐差法通常用于等间距的多组累积物理量测量。)
公式说明:
1. 粘滞系数计算公式 (考虑管壁修正):
η = (ρ - ρ0) * g * d^2 * t / [18 * l * (1 + 2.4 * d/D)]
其中:
ρ : 小球密度
ρ0 : 液体(蓖麻油)密度
d : 小球直径
D : 玻璃管内径
l : 下落距离
t : 下落平均时间
2. 雷诺数 (Re) 判断和修正公式:
Re = ρ0 * v * d / η
其中 v = l / t。
当 Re < 0.1 时,斯托克斯定律完全适用。
当 0.1 <= Re <= 1.0 时,可使用奥辛(Oseen)修正:
η_corrected = η / (1 + 3/16 * Re)
3. 不确定度传递公式 (相对不确定度):
假定 ρ, ρ0, g 的不确定度可忽略,则:
u_r(η) = u_η / η = sqrt( (2 * u_d / d)^2 + (u_t / t)^2 + (u_l / l)^2 + (u_D / D)^2 )
绝对不确定度:
u_η = η * u_r(η)
其中各个量 X 的不确定度 u_X = sqrt( u_A,X^2 + u_B,X^2 )
u_A,X = s_X / sqrt(n)
u_B,X = Δ_inst / sqrt(3)
"""
from utils import (
scientific_round,
calculate_stats,
input_data_group
)
def main():
print("========================================")
print(" 蓖麻油粘滞系数计算 (斯托克斯定律) ")
print("========================================")
# --- 1. 常量设置 ---
G = Decimal("9.80") # 重力加速度 m/s^2
RHO_BALL = Decimal("7800") # 钢球密度 kg/m^3 (默认为钢球,通常实验室用此值)
RHO_OIL = Decimal("960") # 蓖麻油密度 kg/m^3 (随温度变化,常温附近约 960)
print(f"重力加速度 g = {G} m/s^2")
print(f"小球密度 ρ = {RHO_BALL} kg/m^3")
print(f"蓖麻油密度 ρ0 = {RHO_OIL} kg/m^3")
# --- 2. 测量数据输入 ---
print("\n--- 仪器与实验参数设定 ---")
D_mean = Decimal("20.0")
d_mean = Decimal("1.0")
l_mean = Decimal("20.0") # 默认单位 cm,后续转化为 mm 或 m 计算
ans = input("使用默认参数 (玻璃管直径D=20mm, 小球直径d=1mm, 下落距离l=20cm) 吗?[Y/n]: ").strip().lower()
if ans == 'n':
D_mean = Decimal(input("玻璃管直径 D (mm): ").strip() or "20.0")
d_mean = Decimal(input("小球直径 d (mm): ").strip() or "1.0")
l_mean = Decimal(input("下落距离 l (cm): ").strip() or "20.0")
l_mean_mm = l_mean * Decimal("10") # 统一 cm 转为 mm
print("\n--- 输入仪器误差 Δ_inst ---")
delta_D = Decimal(input("D 的仪器误差 (mm, 默认 0): ").strip() or "0")
delta_d = Decimal(input("d 的仪器误差 (mm, 默认 0): ").strip() or "0")
delta_l = Decimal(input("l 的仪器误差 (mm, 默认 0): ").strip() or "0")
delta_t = Decimal(input("t(时间)的仪器误差 (s, 默认 0.01): ").strip() or "0.01")
# D, d, l 我们假设只进行了单次测量或作为已知常数处理,所以只算B类不确定度
D_u = delta_D / Decimal(str(math.sqrt(3)))
d_u = delta_d / Decimal(str(math.sqrt(3)))
l_u = delta_l / Decimal(str(math.sqrt(3)))
# 输入5个时间数据
t_vals = input_data_group("小球下落时间 t", 5, "s")
t_mean, t_u = calculate_stats(t_vals, delta_t)[:2]
# --- 3. 粘滞系数计算 ---
# 统一转化为国际标准单位 (m, kg, s)
D_m = D_mean / Decimal("1000")
d_m = d_mean / Decimal("1000")
l_m = l_mean_mm / Decimal("1000")
# η = (ρ - ρ0) * g * d^2 * t / [18 * l * (1 + 2.4 * d/D)]
correction_factor = Decimal("1") + Decimal("2.4") * (d_m / D_m)
numerator = (RHO_BALL - RHO_OIL) * G * (d_m**2) * t_mean
denominator = Decimal("18") * l_m * correction_factor
eta_val = numerator / denominator
# --- 4. 雷诺数判断与修正 ---
# v = l / t
v_val = l_m / t_mean
# Re = ρ0 * v * d / η
Re = RHO_OIL * v_val * d_m / eta_val
eta_corrected = eta_val
if Re > Decimal("0.1"):
# Oseen 修正
eta_corrected = eta_val / (Decimal("1") + Decimal("3") / Decimal("16") * Re)
# --- 5. 不确定度传播 ---
# 相对不确定度平方和
rel_u_sq = (Decimal("2") * d_u / d_mean)**2 + (t_u / t_mean)**2 + (l_u / l_mean_mm)**2 + (D_u / D_mean)**2
rel_u = Decimal(str(math.sqrt(float(rel_u_sq))))
# 绝对不确定度
eta_u = eta_corrected * rel_u
# --- 6. 修约与输出 ---
eta_final, u_final = scientific_round(eta_corrected, eta_u)
print("\n" + "="*40)
print(" 计算结果")
print("="*40)
print(f"下落时间 t = {t_mean:.3f} ± {t_u:.3f} s")
print(f"下落速度 v = {v_val:.5f} m/s")
print("-" * 40)
print(f"雷诺数 Re = {Re:.4f}")
if Re <= Decimal("0.1"):
print("Re <= 0.1,满足斯托克斯定律条件,无需 Oseen 修正。")
else:
print("Re > 0.1,已应用 Oseen 修正。")
print(f"修正前 η = {eta_val:.4f} Pa·s")
print("-" * 40)
print(f"相对不确定度 u_r = {rel_u*100:.2f}%")
print(f"绝对不确定度 u_η = {eta_u:.4f} Pa·s")
print("-" * 40)
print(f"最终结果: η = {eta_final} ± {u_final} Pa·s")
print("="*40)
if __name__ == "__main__":
main()
+201
View File
@@ -0,0 +1,201 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 杨氏模量计算器 (光杠杆 & 逐差法)\n",
"\n",
"本 Notebook 用于通过光杠杆镜尺法测量金属丝在拉伸过程中的微小伸长量,利用**逐差法**计算金属丝的杨氏弹性模量 $E$,并进行完整的各分量不确定度传递与规范修约。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 杨氏模量计算公式\n",
"根据胡克定律与光杠杆光学放大原理:\n",
"$$E = \\frac{F/S}{\\Delta L / L} = \\frac{4 F L}{\\pi d^2 \\Delta L}$$\n",
"设单个砝码质量为 $m$,增重过程每加 4 个砝码(通过逐差法将 8 个加重、减重平均刻度值 $n_i$ 隔 4 项逐差)产生的刻度尺平均位移为 $\\Delta n_{\\mathrm{avg}}$,光杠杆后足长为 $b$,反射镜至标尺距离为 $D$,则伸长量 $\\Delta L = \\frac{b \\Delta n_{\\mathrm{avg}}}{2 D}$,代入得:\n",
"$$E = \\frac{32 m g L D}{\\pi d^2 b \\Delta n_{\\mathrm{avg}}}$$\n",
"* $L$:金属丝原长\n",
"* $D$:光杠杆镜面到刻度尺标尺距离\n",
"* $d$:金属丝直径(千分尺测量)\n",
"* $b$:光杠杆常数(刀口到后足支点的垂直距离)\n",
"* $m$:单组砝码质量;$g$:重力加速度\n",
"* $\\Delta n_{\\mathrm{avg}}$:4 个砝码引起的标尺平均位移\n",
"\n",
"#### 2. 不确定度传递公式\n",
"* 相对不确定度平方和:\n",
"$$u_r(E) = \\frac{u_E}{E} = \\sqrt{ \\left(\\frac{u_L}{L}\\right)^2 + \\left(\\frac{u_D}{D}\\right)^2 + \\left(2\\frac{u_d}{d}\\right)^2 + \\left(\\frac{u_b}{b}\\right)^2 + \\left(\\frac{u_{\\Delta n}}{\\Delta n_{\\mathrm{avg}}}\\right)^2 }$$\n",
"* 各直接测量量的不确定度按 A 类与仪器 B 类合成:\n",
"$$u_X = \\sqrt{u_{A,X}^2 + u_{B,X}^2}, \\quad u_{A,X} = \\frac{s_X}{\\sqrt{n}}, \\quad u_{B,X} = \\frac{\\Delta_{\\mathrm{inst}}}{\\sqrt{3}}$$"
],
"id": "5763889c1dbb6480"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from decimal import Decimal\n",
"from python.utils import scientific_round, calculate_stats\n",
"\n",
"print(\"杨氏模量模块加载完成。\")"
],
"id": "a70d2b4077726fc0"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 实验参数、几何尺寸与标尺读数输入\n",
"> **提示**:可直接在下方单元格中修改各几何长度的多次测量列表以及加减砝码的刻度尺读数矩阵。"
],
"id": "b3fe9624ea56f3d0"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# --- 常量设置 ---\n",
"M_WEIGHT = Decimal(\"0.350\") # 单个砝码质量 350g = 0.350kg\n",
"G = Decimal(\"9.80\") # 重力加速度 m/s^2\n",
"PI = Decimal(str(math.pi))\n",
"\n",
"# --- 几何长度测量值 (单位: mm,各6次) ---\n",
"L_vals = [Decimal(\"905.0\"), Decimal(\"905.5\"), Decimal(\"904.5\"), Decimal(\"905.0\"), Decimal(\"905.2\"), Decimal(\"904.8\")]\n",
"D_vals = [Decimal(\"1502.0\"), Decimal(\"1501.5\"), Decimal(\"1502.5\"), Decimal(\"1502.0\"), Decimal(\"1501.8\"), Decimal(\"1502.2\")]\n",
"d_vals = [Decimal(\"0.702\"), Decimal(\"0.704\"), Decimal(\"0.701\"), Decimal(\"0.703\"), Decimal(\"0.702\"), Decimal(\"0.703\")]\n",
"b_vals = [Decimal(\"68.20\"), Decimal(\"68.22\"), Decimal(\"68.18\"), Decimal(\"68.20\"), Decimal(\"68.24\"), Decimal(\"68.20\")]\n",
"\n",
"# --- 仪器误差限 Δ_inst (mm) ---\n",
"delta_L = Decimal(\"1.0\")\n",
"delta_D = Decimal(\"1.0\")\n",
"delta_d = Decimal(\"0.005\")\n",
"delta_b = Decimal(\"0.02\")\n",
"delta_n_inst = Decimal(\"0.5\")\n",
"\n",
"# --- 标尺读数 n (0~7 个砝码,单位: mm;每项为 [加重读数, 减重读数]) ---\n",
"n_readings = [\n",
" [Decimal(\"15.2\"), Decimal(\"15.4\")], # 0个\n",
" [Decimal(\"22.1\"), Decimal(\"22.3\")], # 1个\n",
" [Decimal(\"29.0\"), Decimal(\"29.1\")], # 2个\n",
" [Decimal(\"35.8\"), Decimal(\"36.0\")], # 3个\n",
" [Decimal(\"42.7\"), Decimal(\"42.9\")], # 4个\n",
" [Decimal(\"49.5\"), Decimal(\"49.7\")], # 5个\n",
" [Decimal(\"56.3\"), Decimal(\"56.5\")], # 6个\n",
" [Decimal(\"63.1\"), Decimal(\"63.2\")], # 7个\n",
"]\n",
"\n",
"print(\"实验数据加载完成。\")"
],
"id": "b6816ecdb2083f36"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 逐差法处理标尺读数"
],
"id": "7cecf972d1d0806c"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 计算各加重减重的平均读数 n_i\n",
"n_means = [(row[0] + row[1]) / Decimal(\"2\") for row in n_readings]\n",
"\n",
"# 逐差法计算 Δn (隔 4 项相减,相当于 4 个砝码的位移)\n",
"dn_list = []\n",
"print(\"--- 逐差过程 (Δn_j = n_{j+4} - n_j) ---\")\n",
"for j in range(4):\n",
" diff = n_means[j + 4] - n_means[j]\n",
" dn_list.append(diff)\n",
" print(f\"Δn_{j} = n_{j+4} - n_{j} = {diff:.2f} mm\")\n",
"\n",
"dn_mean = sum(dn_list) / Decimal(\"4\")\n",
"variance_dn = sum((x - dn_mean)**2 for x in dn_list) / Decimal(\"3\")\n",
"s_dn = Decimal(str(math.sqrt(float(variance_dn))))\n",
"u_a_dn = s_dn / Decimal(str(math.sqrt(4)))\n",
"u_b_dn = delta_n_inst / Decimal(str(math.sqrt(3)))\n",
"dn_u = Decimal(str(math.sqrt(float(u_a_dn**2 + u_b_dn**2))))\n",
"\n",
"print(f\"\\nΔn 平均值 : {dn_mean:.3f} ± {dn_u:.3f} mm\")"
],
"id": "67a1199d24b1f978"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. 杨氏模量计算与不确定度评定"
],
"id": "66279721f812b579"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 几何参数的均值与不确定度\n",
"L_mean, L_u = calculate_stats(L_vals, delta_L)[:2]\n",
"D_mean, D_u = calculate_stats(D_vals, delta_D)[:2]\n",
"d_mean, d_u = calculate_stats(d_vals, delta_d)[:2]\n",
"b_mean, b_u = calculate_stats(b_vals, delta_b)[:2]\n",
"\n",
"# 转换为国际单位制 (m)\n",
"L_m = L_mean / Decimal(\"1000\")\n",
"D_m = D_mean / Decimal(\"1000\")\n",
"d_m = d_mean / Decimal(\"1000\")\n",
"b_m = b_mean / Decimal(\"1000\")\n",
"dn_m = dn_mean / Decimal(\"1000\")\n",
"\n",
"# E = (32 * m * g * L * D) / (pi * d^2 * b * Δn)\n",
"numerator = Decimal(\"32\") * M_WEIGHT * G * L_m * D_m\n",
"denominator = PI * (d_m**2) * b_m * dn_m\n",
"E_val = numerator / denominator\n",
"\n",
"# 不确定度合成传递\n",
"rel_u_sq = (L_u/L_mean)**2 + (D_u/D_mean)**2 + (Decimal(\"2\")*d_u/d_mean)**2 + (b_u/b_mean)**2 + (dn_u/dn_mean)**2\n",
"rel_u = Decimal(str(math.sqrt(float(rel_u_sq))))\n",
"E_u = E_val * rel_u\n",
"\n",
"# 科学修约 (以 10^11 Pa 数量级表示)\n",
"E_11 = E_val / Decimal(\"1e11\")\n",
"E_u_11 = E_u / Decimal(\"1e11\")\n",
"E_final, u_final = scientific_round(E_11, E_u_11)\n",
"\n",
"print(\"=\" * 45)\n",
"print(\" 杨 氏 模 量 计 算 结 果 \")\n",
"print(\"=\" * 45)\n",
"print(f\"金属丝长度 L : {L_mean:.2f} ± {L_u:.2f} mm\")\n",
"print(f\"镜面到尺距离 D: {D_mean:.2f} ± {D_u:.2f} mm\")\n",
"print(f\"金属丝直径 d : {d_mean:.4f} ± {d_u:.4f} mm\")\n",
"print(f\"光杠杆臂长 b : {b_mean:.3f} ± {b_u:.3f} mm\")\n",
"print(f\"标尺位移 Δn : {dn_mean:.3f} ± {dn_u:.3f} mm (4个砝码对应位移)\")\n",
"print(\"-\" * 45)\n",
"print(f\"杨氏模量 E (原始): {E_val:.4e} Pa\")\n",
"print(f\"相对不确定度 u_r : {rel_u * 100:.2f}%\")\n",
"print(f\"绝对不确定度 u_E : {E_u:.4e} Pa\")\n",
"print(\"-\" * 45)\n",
"print(f\"★ 最终结果表示 : E = {E_final} ± {u_final} × 10^11 Pa\")\n",
"print(\"=\" * 45)"
],
"id": "d4864c1fd01816d6"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+150
View File
@@ -0,0 +1,150 @@
import math
from decimal import Decimal
"""
Young's Modulus Calculator (Optical Lever & Successive Difference Method)
杨氏模量计算器 (光杠杆 & 逐差法)
不确定度传递公式:
1. 杨氏模量公式:
E = (32 * m * g * L * D) / (π * d^2 * b * Δn_avg)
其中 Δn_avg 是 4 个砝码对应的平均刻度位移(由 8 个刻度值通过逐差法求得)。
2. 相对不确定度传递公式:
u_r(E) = u_E / E = sqrt( (u_L/L)^2 + (u_D/D)^2 + (2 * u_d/d)^2 + (u_b/b)^2 + (u_Δn/Δn_avg)^2 )
3. 合成不确定度:
u_E = E * u_r(E)
其中各物理量 X 的不确定度 u_X = sqrt( u_A,X^2 + u_B,X^2 )
u_A,X = s_X / sqrt(n)
u_B,X = Δ_inst / sqrt(3)
"""
from utils import (
scientific_round,
calculate_stats,
input_data_group
)
def main():
# --- 1. 常量设置 ---
M_WEIGHT = Decimal("0.350") # 单个砝码质量 350g = 0.350kg
G = Decimal("9.80") # 重力加速度
PI = Decimal(str(math.pi))
print("========================================")
print(" 杨氏模量计算 (光杠杆 & 逐差法) ")
print("========================================")
print(f"单个砝码质量 m = {M_WEIGHT} kg")
print(f"重力加速度 g = {G} m/s^2")
# --- 2. 几何长度输入 (各6次测量) ---
# L: 钢丝长度, D: 镜面到刻度尺距离, d: 钢丝直径, b: 光杠杆臂长
L_vals = input_data_group("钢丝长度 L", 6, "mm")
D_vals = input_data_group("镜面到尺距离 D", 6, "mm")
d_vals = input_data_group("钢丝直径 d", 6, "mm")
b_vals = input_data_group("光杠杆臂长 b", 6, "mm")
print("\n--- 输入仪器误差 Δ_inst ---")
delta_L = Decimal(input("L 的仪器误差 (mm, 默认 1.0): ").strip() or "1.0")
delta_D = Decimal(input("D 的仪器误差 (mm, 默认 1.0): ").strip() or "1.0")
delta_d = Decimal(input("d 的仪器误差 (mm, 默认 0.005): ").strip() or "0.005")
delta_b = Decimal(input("b 的仪器误差 (mm, 默认 0.02): ").strip() or "0.02")
L_mean, L_u = calculate_stats(L_vals, delta_L)[:2]
D_mean, D_u = calculate_stats(D_vals, delta_D)[:2]
d_mean, d_u = calculate_stats(d_vals, delta_d)[:2]
b_mean, b_u = calculate_stats(b_vals, delta_b)[:2]
# --- 3. 刻度值输入 (0-7个砝码, 加重+减重) ---
print("\n--- 输入刻度尺读数 n (单位: mm) ---")
n_up = []
n_down = []
for i in range(8):
while True:
try:
line = input(f"砝码数量 {i} (加重, 减重): ").replace(',', ' ').split()
if len(line) != 2:
print("请输入两个数值(空格或逗号隔开)")
continue
n_up.append(Decimal(line[0]))
n_down.append(Decimal(line[1]))
break
except Exception:
print("输入无效!")
delta_n_inst = Decimal(input("刻度尺仪器误差 (mm, 默认 0.5): ").strip() or "0.5")
# 计算平均读数 n_i
n_means = [(u + d) / 2 for u, d in zip(n_up, n_down)]
print("\n--- 中间量 (加重与减重的平均值 n_i) ---")
for i, val in enumerate(n_means):
print(f"n_{i} = {val} mm")
# 逐差法计算 Δn (隔 4 项相减)
# Δn_j = n_{j+4} - n_j, j = 0,1,2,3
dn_list = []
print("\n--- 逐差计算过程 ---")
for j in range(4):
diff = n_means[j+4] - n_means[j]
dn_list.append(diff)
print(f"Δn_{j} = n_{j+4} - n_{j} = {diff} mm")
# Δn 的平均值及不确定度
dn_mean = sum(dn_list) / Decimal("4")
# A类: 针对这 4 个差值
variance_dn = sum((x - dn_mean)**2 for x in dn_list) / Decimal("3")
s_dn = Decimal(str(math.sqrt(float(variance_dn))))
u_a_dn = s_dn / Decimal(str(math.sqrt(4)))
# B类: 刻度尺误差
# 因为 n_i = (n_up + n_down)/2, Δn = n_high - n_low
# 传播得 u_B(Δn) = Δ_inst / sqrt(3)
u_b_dn = delta_n_inst / Decimal(str(math.sqrt(3)))
dn_u = Decimal(str(math.sqrt(float(u_a_dn**2 + u_b_dn**2))))
# --- 4. 杨氏模量计算 ---
# 全部转为标准单位 (m)
L_m = L_mean / 1000
D_m = D_mean / 1000
d_m = d_mean / 1000
b_m = b_mean / 1000
dn_m = dn_mean / 1000
# E = (32 * m * g * L * D) / (pi * d^2 * b * Δn)
# 这里的 Δn 对应 4 个砝码的位移
numerator = Decimal("32") * M_WEIGHT * G * L_m * D_m
denominator = PI * (d_m**2) * b_m * dn_m
E_val = numerator / denominator
# --- 5. 不确定度传播 ---
# rel_u = sqrt( (uL/L)^2 + (uD/D)^2 + (2*ud/d)^2 + (ub/b)^2 + (udn/dn)^2 )
rel_u_sq = (L_u/L_mean)**2 + (D_u/D_mean)**2 + (Decimal("2")*d_u/d_mean)**2 + (b_u/b_mean)**2 + (dn_u/dn_mean)**2
rel_u = Decimal(str(math.sqrt(float(rel_u_sq))))
E_u = E_val * rel_u
# --- 6. 修约与输出 ---
# 通常用 10^11 Pa 表示
E_11 = E_val / Decimal("1e11")
E_u_11 = E_u / Decimal("1e11")
E_final, u_final = scientific_round(E_11, E_u_11)
print("\n" + "="*40)
print(" 计算结果")
print("="*40)
print(f"L = {L_mean:.2f} ± {L_u:.2f} mm")
print(f"D = {D_mean:.2f} ± {D_u:.2f} mm")
print(f"d = {d_mean:.4f} ± {d_u:.4f} mm")
print(f"b = {b_mean:.3f} ± {b_u:.3f} mm")
print(f"Δn = {dn_mean:.3f} ± {dn_u:.3f} mm (4个砝码位移)")
print("-" * 40)
print(f"杨氏模量 E (原始): {E_val:.4e} Pa")
print(f"相对不确定度 u_r: {rel_u*100:.2f}%")
print("-" * 40)
print(f"最终结果: E = {E_final} ± {u_final} × 10^11 Pa")
print("="*40)
if __name__ == "__main__":
main()
+137
View File
@@ -0,0 +1,137 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 角度直接测量与不确定度评定\n",
"\n",
"本 Notebook 用于对分光计等仪器测得的角度多次测量数据(支持度分格式 `度.分`)进行不确定度合成与保留一位有效数字的规范修约输出。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 角度单位换算与平均值计算\n",
"角度采用“分(arcminute)”为内部基准单位换算:\n",
"$$D^\\circ M' = D \\times 60' + M'$$\n",
"对 $n$ 次测量值 $\\theta_1, \\theta_2, \\dots, \\theta_n$(以分为单位):\n",
"$$\\bar{\\theta} = \\frac{1}{n} \\sum_{i=1}^n \\theta_i$$\n",
"$$s = \\sqrt{\\frac{1}{n-1} \\sum_{i=1}^n (\\theta_i - \\bar{\\theta})^2}$$\n",
"\n",
"#### 2. 不确定度评定公式\n",
"* **A 类不确定度**:\n",
"$$u_A = \\frac{s}{\\sqrt{n}}$$\n",
"* **B 类不确定度**(分光计游标盘分度值误差 $\\Delta_{\\mathrm{inst}}$ 通常为 $1'$):\n",
"$$u_B = \\frac{\\Delta_{\\mathrm{inst}}}{\\sqrt{3}}$$\n",
"* **合成不确定度**:\n",
"$$u = \\sqrt{u_A^2 + u_B^2}$$\n",
"\n",
"#### 3. 结果修约规则\n",
"不确定度 $u$ 按照“四舍六入五凑偶”保留一位有效数字,角度平均值末位与不确定度对齐,并还原输出为度分格式 $D^\\circ M'$。"
],
"id": "b15a8bae68dd9273"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from decimal import Decimal\n",
"from python.utils import parse_angle_to_minutes, format_minutes_as_angle, scientific_round\n",
"\n",
"print(\"角度换算与修约模块加载完成。\")"
],
"id": "afc36384df4dec97"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 角度测量数据与分度值输入\n",
"> **输入格式**:字符串 `'度.分'`(例如 `'120.15'` 代表 $120^\\circ 15'$)。"
],
"id": "2d31b33f8ef516db"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 测量数据列表 (度.分 格式)\n",
"angle_data = [\"120.15\", \"120.16\", \"120.14\", \"120.15\", \"120.17\", \"120.15\"]\n",
"\n",
"# 仪器分度值 (单位: 分 ')\n",
"res_str = \"1\"\n",
"\n",
"print(f\"输入角度数据: {angle_data}\")\n",
"print(f\"仪器分度值: {res_str} '\")"
],
"id": "50959966653d1094"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 统计计算与修约输出"
],
"id": "d91d9838fb92eb89"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 转换为内部单位“分”\n",
"data_minutes = [parse_angle_to_minutes(s) for s in angle_data]\n",
"res = Decimal(res_str)\n",
"n = len(data_minutes)\n",
"\n",
"# 1. 平均值与标准差\n",
"mean_minutes = sum(data_minutes) / n\n",
"variance = sum((x - mean_minutes) ** 2 for x in data_minutes) / (n - 1) if n > 1 else Decimal(\"0\")\n",
"s = Decimal(str(math.sqrt(float(variance))))\n",
"\n",
"# 2. A类、B类及合成不确定度\n",
"u_A = s / Decimal(str(math.sqrt(n))) if n > 1 else Decimal(\"0\")\n",
"u_B = res / Decimal(str(math.sqrt(3)))\n",
"u = Decimal(str(math.sqrt(float(u_A**2 + u_B**2))))\n",
"\n",
"# 3. 科学修约与格式还原\n",
"u_float = float(u)\n",
"if u_float == 0:\n",
" final_result_str = f\"θ = {format_minutes_as_angle(mean_minutes)} ± 0'\"\n",
"else:\n",
" first_digit_pos = math.floor(math.log10(u_float))\n",
" prec = Decimal('1e' + str(first_digit_pos))\n",
" mean_final_val, u_final = scientific_round(mean_minutes, u)\n",
" mean_str = format_minutes_as_angle(mean_final_val, prec)\n",
" final_result_str = f\"θ = {mean_str} ± {u_final}'\"\n",
"\n",
"print(\"=\" * 45)\n",
"print(\" 角 度 测 量 不 确 定 度 分 析 \")\n",
"print(\"=\" * 45)\n",
"print(f\"测量次数 n : {n}\")\n",
"print(f\"角度平均值 : {format_minutes_as_angle(mean_minutes)} ({mean_minutes:.4f}')\")\n",
"print(f\"样本标准差 s : {s:.6f}'\")\n",
"print(f\"A 类不确定度 u_A : {u_A:.6f}'\")\n",
"print(f\"B 类不确定度 u_B : {u_B:.6f}'\")\n",
"print(f\"合成不确定度 u : {u:.6f}'\")\n",
"print(\"-\" * 45)\n",
"print(f\"★ 最终修约结果 : {final_result_str}\")\n",
"print(\"=\" * 45)"
],
"id": "ef15abbb8e0d991c"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+82
View File
@@ -0,0 +1,82 @@
import math
from decimal import Decimal
from utils import (
parse_angle_to_minutes,
format_minutes_as_angle,
scientific_round
)
def calc_uncertainty(data_strs, res_str="1"):
# 转换为分钟进行高精度计算
data = [parse_angle_to_minutes(s) for s in data_strs]
res = Decimal(res_str) # 仪器误差,单位:分
n = len(data)
# 1. 计算平均值
sum_val = sum(data)
mean = sum_val / n
# 2. 计算标准差 s
if n > 1:
variance = sum((x - mean) ** 2 for x in data) / (n - 1)
s = Decimal(str(math.sqrt(float(variance))))
else:
s = Decimal('0')
# 3. A类不确定度 u_A
u_A = s / Decimal(str(math.sqrt(n)))
# 4. B类不确定度 u_B (仪器误差)
u_B = res / Decimal(str(math.sqrt(3)))
# 5. 合成不确定度 u
u = Decimal(str(math.sqrt(float(u_A**2 + u_B**2))))
return mean, s, u_A, u_B, u
def format_final_result(mean_minutes, u_minutes):
"""
按照“四舍六入五凑偶”修约:
1. 不确定度 u 保留一位有效数字
2. 平均值末位与 u 对齐
"""
u_float = float(u_minutes)
if u_float == 0:
return f"θ = {format_minutes_as_angle(mean_minutes)} ± 0'"
first_digit_pos = math.floor(math.log10(u_float))
prec = Decimal('1e' + str(first_digit_pos))
mean_final_val, u_final = scientific_round(mean_minutes, u_minutes)
mean_str = format_minutes_as_angle(mean_final_val, prec)
u_str = f"{u_final}'"
return f"θ = {mean_str} ± {u_str}"
if __name__ == "__main__":
print("=== 角度不确定度计算器 ===")
print("输入格式: '度.分' (如 120.15 表示 120°15'),多个数据用空格隔开。")
try:
user_input = input("请输入数据:").split()
if not user_input:
print("未输入数据!")
else:
res_input = input("请输入仪器分度值 (单位: 分,默认 1):").strip() or "1"
mean_v, s, u_A, u_B, u = calc_uncertainty(user_input, res_input)
print("\n--- 中间计算过程 ---")
print(f"平均值: {format_minutes_as_angle(mean_v)} ({mean_v:.4f}')")
print(f"标准差 s: {s:.6f}'")
print(f"A类不确定度 u_A: {u_A:.6f}'")
print(f"B类不确定度 u_B: {u_B:.6f}'")
print(f"合成不确定度 u: {u:.6f}'")
print("\n--- 最终修约结果 (四舍六入五凑偶) ---")
print(format_final_result(mean_v, u))
except Exception as e:
print(f"错误: {e}")
+139
View File
@@ -0,0 +1,139 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 长度直接测量与不确定度评定\n",
"\n",
"本 Notebook 用于对多次长度直接测量数据进行 A 类不确定度、B 类不确定度及合成不确定度计算,并严格按照“四舍六入五凑偶”规则对测量结果进行科学修约与末位对齐。\n",
"\n",
"---\n",
"### 实验原理与数学公式\n",
"\n",
"#### 1. 算术平均值与样本标准差\n",
"对 $n$ 次独立等精度直接测量值 $x_1, x_2, \\dots, x_n$:\n",
"$$\\bar{x} = \\frac{1}{n} \\sum_{i=1}^n x_i$$\n",
"$$s = \\sqrt{\\frac{1}{n-1} \\sum_{i=1}^n (x_i - \\bar{x})^2}$$\n",
"\n",
"#### 2. A 类、B 类及合成不确定度\n",
"* **A 类不确定度**(由有限次测量随机效应引起):\n",
"$$u_A = \\frac{s}{\\sqrt{n}}$$\n",
"* **B 类不确定度**(由测量仪器极限误差 $\\Delta_{\\mathrm{inst}}$ 引起,假定均匀分布):\n",
"$$u_B = \\frac{\\Delta_{\\mathrm{inst}}}{\\sqrt{3}}$$\n",
"* **合成标准不确定度**:\n",
"$$u = \\sqrt{u_A^2 + u_B^2}$$\n",
"\n",
"#### 3. 修约与结果表示\n",
"* 不确定度 $u$ 按照“四舍六入五凑偶”原则保留一位有效数字。\n",
"* 测量平均值末位与不确定度的有效位数对齐。"
],
"id": "1ed33dfddc944ff0"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from decimal import Decimal, ROUND_HALF_EVEN\n",
"from python.utils import get_decimal_places, scientific_round\n",
"\n",
"print(\"工具函数加载完成。\")"
],
"id": "709179017567e25d"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. 测量数据与仪器参数设置\n",
"> **提示**:直接在下方修改测量数据列表 `raw_data`(字符串或数值)与仪器分度值/允差 `res_str` 即可。"
],
"id": "6e9499ceb295ab05"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 测量数据列表 (字符串格式保留输入精度)\n",
"raw_data = [\"10.25\", \"10.24\", \"10.26\", \"10.25\", \"10.24\", \"10.25\"]\n",
"\n",
"# 仪器分度值 / 仪器误差限 Δ_inst\n",
"res_str = \"0.05\"\n",
"\n",
"print(f\"输入测量数据 (n={len(raw_data)}): {raw_data}\")\n",
"print(f\"仪器误差限 Δ_inst: {res_str}\")"
],
"id": "722fceaefcc9ac13"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. 不确定度计算与科学修约"
],
"id": "376599ba7264087b"
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def calc_uncertainty(data_strs, res_str=\"0.05\"):\n",
" data = [Decimal(str(s)) for s in data_strs]\n",
" res = Decimal(str(res_str))\n",
" n = len(data)\n",
" \n",
" # 1. 原始精度平均值\n",
" places = get_decimal_places(data_strs)\n",
" sum_val = sum(data)\n",
" mean = sum_val / n\n",
" mean_final = mean.quantize(Decimal('1.' + '0' * places), rounding=ROUND_HALF_EVEN)\n",
" \n",
" # 2. 样本标准差 s\n",
" variance = sum((x - mean) ** 2 for x in data) / (n - 1) if n > 1 else Decimal(\"0\")\n",
" s = Decimal(str(math.sqrt(float(variance))))\n",
" \n",
" # 3. A 类不确定度\n",
" u_A = s / Decimal(str(math.sqrt(n))) if n > 1 else Decimal(\"0\")\n",
" \n",
" # 4. B 类不确定度\n",
" u_B = res / Decimal(str(math.sqrt(3)))\n",
" \n",
" # 5. 合成不确定度\n",
" u = Decimal(str(math.sqrt(float(u_A**2 + u_B**2))))\n",
" \n",
" return mean_final, mean, s, u_A, u_B, u\n",
"\n",
"mean_display, mean_raw, s, u_A, u_B, u = calc_uncertainty(raw_data, res_str)\n",
"mean_final, u_final = scientific_round(mean_raw, u)\n",
"\n",
"print(\"=\" * 40)\n",
"print(\" 长 度 测 量 不 确 定 度 分 析 \")\n",
"print(\"=\" * 40)\n",
"print(f\"测量次数 n : {len(raw_data)}\")\n",
"print(f\"算术平均值 : {mean_raw:.6f}\")\n",
"print(f\"样本标准差 s : {s:.6f}\")\n",
"print(f\"A 类不确定度 u_A : {u_A:.6f}\")\n",
"print(f\"B 类不确定度 u_B : {u_B:.6f}\")\n",
"print(f\"合成不确定度 u : {u:.6f}\")\n",
"print(\"-\" * 40)\n",
"print(f\"★ 最终修约结果 : L = {mean_final} ± {u_final}\")\n",
"print(\"=\" * 40)"
],
"id": "5fc60b2526bdc755"
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+61
View File
@@ -0,0 +1,61 @@
import math
from decimal import Decimal, ROUND_HALF_EVEN
from utils import get_decimal_places, scientific_round
def calc_uncertainty(data_strs, res_str="0.05"):
# 转换为 Decimal 进行高精度计算
data = [Decimal(s) for s in data_strs]
res = Decimal(res_str)
n = len(data)
# 1. 计算平均值
places = get_decimal_places(data_strs)
sum_val = sum(data)
mean = sum_val / n
# 修改:平均值修约使用“四舍六入五凑偶”
mean_final = mean.quantize(Decimal('1.' + '0' * places), rounding=ROUND_HALF_EVEN)
# 2. 计算标准差 s
variance = sum((x - mean) ** 2 for x in data) / (n - 1)
s = Decimal(str(math.sqrt(float(variance))))
# 3. A类不确定度 u_A
u_A = s / Decimal(str(math.sqrt(n)))
# 4. B类不确定度 u_B (仪器误差)
u_B = res / Decimal(str(math.sqrt(3)))
# 5. 合成不确定度 u
u = Decimal(str(math.sqrt(float(u_A**2 + u_B**2))))
return mean_final, s, u_A, u_B, u
def format_final_result(mean, u):
"""
按照“四舍六入五凑偶”修约:
1. 不确定度 u 保留一位有效数字
2. 平均值末位与 u 对齐
"""
mean_final, u_final = scientific_round(mean, u)
return f"f = {mean_final} ± {u_final}"
if __name__ == "__main__":
# ... (后续输入输出逻辑保持不变)
print("请输入数据,用空格分隔:")
raw_input = input().split()
print("请输入仪器分度值(默认 0.05):")
res_input = input().strip() or "0.05"
mean_f, s, u_A, u_B, u = calc_uncertainty(raw_input, res_input)
print("\n--- 中间计算过程 (高精度展示) ---")
print(f"平均值 (原始精度): {mean_f}")
print(f"标准差 s: {s:.6f}")
print(f"A类不确定度 u_A: {u_A:.6f}")
print(f"B类不确定度 u_B: {u_B:.6f}")
print(f"合成不确定度 u: {u:.6f}")
print("\n--- 最终修约结果 (四舍六入五凑偶) ---")
print(format_final_result(mean_f, u))
+16
View File
@@ -0,0 +1,16 @@
from python.utils.formatting import (
get_decimal_places,
scientific_round,
parse_angle_to_minutes,
format_minutes_as_angle
)
from python.utils.stats import (
calculate_stats,
linear_regression
)
from python.utils.io import (
input_float,
input_decimal,
input_int,
input_data_group
)
+76
View File
@@ -0,0 +1,76 @@
import math
from decimal import Decimal, ROUND_HALF_EVEN
def get_decimal_places(data_strings):
"""获取输入数据中小数点后的位数,用于自适应展示"""
max_places = 0
for s in data_strings:
if '.' in s:
places = len(s.split('.')[1])
max_places = max(max_places, places)
return max_places
def scientific_round(value, uncertainty):
"""
按照“四舍六入五凑偶”修约:
1. 不确定度 u 保留一位有效数字
2. 平均值/结果末位与 u 对齐
"""
if uncertainty <= 0:
return str(value), "0"
d_val = Decimal(str(value))
d_unc = Decimal(str(uncertainty))
u_float = float(d_unc)
first_digit_pos = math.floor(math.log10(u_float))
prec = Decimal('1e' + str(first_digit_pos))
u_final = d_unc.quantize(prec, rounding=ROUND_HALF_EVEN)
val_final = d_val.quantize(prec, rounding=ROUND_HALF_EVEN)
return val_final, u_final
def parse_angle_to_minutes(s):
"""
将输入解析为内部统一单位:分钟(Decimal)。
支持格式:
1. 'D.M' -> D度M分 (例如 '120.15' -> 120*60 + 15 = 7215分)
2. 'D' (纯数字无点) -> D度 (例如 '120' -> 120*60 = 7200分)
3. 'D.M.S' -> D度M分S秒 (例如 '120.15.30' -> 7215.5分)
"""
parts = s.split('.')
if len(parts) == 1:
return Decimal(parts[0]) * 60
elif len(parts) == 2:
return Decimal(parts[0]) * 60 + Decimal(parts[1])
else:
res = Decimal(parts[0]) * 60 + Decimal(parts[1])
if len(parts) >= 3:
res += Decimal(parts[2]) / 60
return res
def format_minutes_as_angle(minutes, prec=None):
"""
将总分钟数转换为 D° M' 格式,支持保持对齐精度。
"""
neg = minutes < 0
minutes = abs(minutes)
d = int(minutes // 60)
m = minutes % 60
if m >= 60:
d += 1
m -= 60
if prec is not None and prec < 1:
places = abs(prec.as_tuple().exponent)
m_str = format(m, f'.{places}f')
else:
if m == int(m):
m_str = str(int(m))
else:
m_str = format(m, 'f').rstrip('0').rstrip('.')
return f"{'-' if neg else ''}{d}°{m_str}'"
+59
View File
@@ -0,0 +1,59 @@
from decimal import Decimal
def input_float(prompt, default=None):
"""输入一个浮点数值,支持默认值"""
while True:
try:
suffix = f" (默认 {default})" if default is not None else ""
val = input(f"{prompt}{suffix}: ").strip()
if not val and default is not None:
return float(default)
if not val:
continue
return float(val)
except Exception:
print(" 输入无效,请输入数字。")
def input_decimal(prompt, default=None):
"""输入一个 Decimal 值,支持默认值"""
while True:
try:
suffix = f" (默认 {default})" if default is not None else ""
val = input(f"{prompt}{suffix}: ").strip()
if not val and default is not None:
return Decimal(str(default))
if not val:
continue
return Decimal(val)
except Exception:
print(" 输入无效,请输入数字。")
def input_int(prompt, default=None):
"""输入一个整数,支持默认值"""
while True:
try:
suffix = f" (默认 {default})" if default is not None else ""
val = input(f"{prompt}{suffix}: ").strip()
if not val and default is not None:
return default
if not val:
continue
return int(val)
except Exception:
print(" 输入无效,请输入整数。")
def input_data_group(name, count, unit=""):
"""输入一组重复测量的数值"""
prompt_unit = f" (单位: {unit})" if unit else ""
print(f"\n请输入 {name} 的 {count} 次测量值{prompt_unit}:")
data = []
for i in range(count):
while True:
try:
val = input(f"第 {i+1} 次 = ").strip()
if not val: continue
data.append(Decimal(val))
break
except Exception:
print("输入无效,请输入数字。")
return data
+59
View File
@@ -0,0 +1,59 @@
import math
from decimal import Decimal
def calculate_stats(data_list, delta_inst):
"""
计算一组数据的平均值、A类、B类及合成不确定度。
支持输入 list of Decimal 或 list of float/str/int。
返回: (mean, u_combined, u_a, u_b, s)
"""
n = len(data_list)
decimal_data = [Decimal(str(x)) for x in data_list]
mean = sum(decimal_data) / Decimal(n)
if n > 1:
variance = sum((x - mean)**2 for x in decimal_data) / Decimal(n - 1)
s = Decimal(str(math.sqrt(float(variance))))
u_a = s / Decimal(str(math.sqrt(n)))
else:
s = Decimal("0")
u_a = Decimal("0")
u_b = Decimal(str(delta_inst)) / Decimal(str(math.sqrt(3)))
u_combined = Decimal(str(math.sqrt(float(u_a**2 + u_b**2))))
return mean, u_combined, u_a, u_b, s
def linear_regression(x_list, y_list):
"""
最小二乘法线性回归: y = k·x + b
返回: (k, b, r, u_k)
u_k = |k| · √[(1/r² − 1) / (n − 2)]
支持 input numbers as Decimal or float.
"""
n = len(x_list)
x_dec = [Decimal(str(x)) for x in x_list]
y_dec = [Decimal(str(y)) for y in y_list]
x_mean = sum(x_dec) / Decimal(n)
y_mean = sum(y_dec) / Decimal(n)
L_xx = sum((x - x_mean)**2 for x in x_dec)
L_yy = sum((y - y_mean)**2 for y in y_dec)
L_xy = sum((x_dec[i] - x_mean) * (y_dec[i] - y_mean) for i in range(n))
k = L_xy / L_xx if L_xx != 0 else Decimal("0")
b = y_mean - k * x_mean
denom = Decimal(str(math.sqrt(float(L_xx * L_yy)))) if L_xx * L_yy > 0 else Decimal("1")
r = L_xy / denom
r_float = float(r)
if abs(r_float) < 1.0 and n > 2:
u_k_float = float(abs(k)) * math.sqrt((1.0 / (r_float**2) - 1.0) / (n - 2))
else:
u_k_float = 0.0
u_k = Decimal(str(u_k_float))
return k, b, r, u_k