init
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
import math
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
"""
|
||||
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 scientific_round(value, uncertainty):
|
||||
"""
|
||||
按照"四舍六入五凑偶"修约:
|
||||
1. 不确定度 u 保留一位有效数字
|
||||
2. 平均值末位与 u 对齐
|
||||
"""
|
||||
if uncertainty <= 0:
|
||||
return str(value), "0"
|
||||
|
||||
u_float = float(uncertainty)
|
||||
first_digit_pos = math.floor(math.log10(u_float))
|
||||
prec = Decimal('1e' + str(first_digit_pos))
|
||||
|
||||
u_final = uncertainty.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
val_final = value.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
return val_final, u_final
|
||||
|
||||
def calculate_stats(data_list, delta_inst):
|
||||
"""
|
||||
计算一组数据的平均值、A类、B类及合成不确定度
|
||||
u(X) = sqrt( u_A^2 + u_B^2 )
|
||||
u_A = s / sqrt(n)
|
||||
u_B = Δ_inst / sqrt(3)
|
||||
"""
|
||||
n = len(data_list)
|
||||
mean = sum(data_list) / Decimal(n)
|
||||
|
||||
if n > 1:
|
||||
variance = sum((x - mean)**2 for x in data_list) / Decimal(n - 1)
|
||||
s = Decimal(str(math.sqrt(float(variance))))
|
||||
u_a = s / Decimal(str(math.sqrt(n)))
|
||||
else:
|
||||
u_a = Decimal("0")
|
||||
|
||||
u_b = Decimal(delta_inst) / Decimal(str(math.sqrt(3)))
|
||||
u_combined = Decimal(str(math.sqrt(float(u_a**2 + u_b**2))))
|
||||
|
||||
return mean, u_a, u_b, u_combined
|
||||
|
||||
def input_decimal(prompt, default=None):
|
||||
"""输入一个 Decimal 值,支持默认值"""
|
||||
while True:
|
||||
try:
|
||||
suffix = f" (默认 {default})" if default 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 else ""
|
||||
val = input(f"{prompt}{suffix}: ").strip()
|
||||
if not val and default is not None:
|
||||
return default
|
||||
return int(val)
|
||||
except Exception:
|
||||
print("输入无效,请输入整数。")
|
||||
|
||||
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_a_R0, u_b_R0, u_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()
|
||||
@@ -0,0 +1,140 @@
|
||||
import math
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
"""
|
||||
Newton's Rings Curvature Radius Calculator (Successive Difference Method)
|
||||
牛顿环曲率半径计算器 (逐差法)
|
||||
|
||||
参考 lenth.py 的高精度与不确定度修约逻辑。
|
||||
"""
|
||||
|
||||
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"
|
||||
|
||||
u_float = float(uncertainty)
|
||||
# 找到第一位非零数字的位置
|
||||
first_digit_pos = math.floor(math.log10(u_float))
|
||||
prec = Decimal('1e' + str(first_digit_pos))
|
||||
|
||||
# 不确定度修约
|
||||
u_final = uncertainty.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
# 平均值修约,保持与不确定度末位对齐
|
||||
val_final = value.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
return val_final, u_final
|
||||
|
||||
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()
|
||||
@@ -0,0 +1,160 @@
|
||||
import math
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
"""
|
||||
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(λ)
|
||||
"""
|
||||
|
||||
def scientific_round(value, uncertainty):
|
||||
"""
|
||||
按照“四舍六入五凑偶”修约:
|
||||
1. 不确定度 u 保留一位有效数字
|
||||
2. 平均值末位与 u 对齐
|
||||
"""
|
||||
if uncertainty == 0:
|
||||
return str(value), "0"
|
||||
|
||||
u_float = float(uncertainty)
|
||||
first_digit_pos = math.floor(math.log10(u_float))
|
||||
prec = Decimal('1e' + str(first_digit_pos))
|
||||
|
||||
u_final = uncertainty.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
val_final = value.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
return val_final, u_final
|
||||
|
||||
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()
|
||||
@@ -0,0 +1,257 @@
|
||||
import math
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
"""
|
||||
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)
|
||||
"""
|
||||
|
||||
def scientific_round(value, uncertainty):
|
||||
"""
|
||||
按照“四舍六入五凑偶”修约:
|
||||
1. 不确定度 u 保留一位有效数字
|
||||
2. 平均值末位与 u 对齐
|
||||
"""
|
||||
if uncertainty <= 0:
|
||||
return str(value), "0"
|
||||
|
||||
u_float = float(uncertainty)
|
||||
first_digit_pos = math.floor(math.log10(u_float))
|
||||
prec = Decimal('1e' + str(first_digit_pos))
|
||||
|
||||
u_final = uncertainty.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
val_final = value.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
return val_final, u_final
|
||||
|
||||
def calculate_stats(data_list, delta_inst):
|
||||
"""计算一组数据的平均值、A类、B类及合成不确定度"""
|
||||
n = len(data_list)
|
||||
mean = sum(data_list) / Decimal(n)
|
||||
|
||||
if n > 1:
|
||||
variance = sum((x - mean)**2 for x in data_list) / Decimal(n - 1)
|
||||
s = Decimal(str(math.sqrt(float(variance))))
|
||||
u_a = s / Decimal(str(math.sqrt(n)))
|
||||
else:
|
||||
u_a = Decimal("0")
|
||||
|
||||
u_b = Decimal(delta_inst) / Decimal(str(math.sqrt(3)))
|
||||
u_combined = Decimal(str(math.sqrt(float(u_a**2 + u_b**2))))
|
||||
|
||||
return mean, u_combined
|
||||
|
||||
def linear_regression(x_list, y_list):
|
||||
"""
|
||||
对 (x, y) 列表进行线性回归,返回斜率 k, 截距 b, 及斜率的标准不确定度 u_k
|
||||
"""
|
||||
n = len(x_list)
|
||||
x_mean = sum(x_list) / Decimal(n)
|
||||
y_mean = sum(y_list) / Decimal(n)
|
||||
|
||||
L_xx = sum((x - x_mean)**2 for x in x_list)
|
||||
L_yy = sum((y - y_mean)**2 for y in y_list)
|
||||
L_xy = sum((x_list[i] - x_mean) * (y_list[i] - y_mean) for i in range(n))
|
||||
|
||||
# 斜率
|
||||
k = L_xy / L_xx
|
||||
# 截距
|
||||
b = y_mean - k * x_mean
|
||||
|
||||
# 相关系数 r
|
||||
r = L_xy / Decimal(str(math.sqrt(float(L_xx * L_yy))))
|
||||
|
||||
# 斜率的标准不确定度 u_k
|
||||
# u_k = k * sqrt( (1/r^2 - 1) / (n - 2) )
|
||||
r_float = float(r)
|
||||
if abs(r_float) < 1.0:
|
||||
u_k_float = float(k) * math.sqrt( (1.0 / (r_float**2) - 1.0) / (n - 2) )
|
||||
else:
|
||||
u_k_float = 0.0
|
||||
u_k = Decimal(str(abs(u_k_float)))
|
||||
|
||||
return k, b, r, u_k
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
# 输入内径 d1 (6次)
|
||||
d1_vals = input_data_group("铁环内径 d1", 6, "mm")
|
||||
d1_mean, d1_u = calculate_stats(d1_vals, delta_d)
|
||||
|
||||
# 输入外径 d2 (6次)
|
||||
d2_vals = input_data_group("铁环外径 d2", 6, "mm")
|
||||
d2_mean, d2_u = calculate_stats(d2_vals, delta_d)
|
||||
|
||||
# --- 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()
|
||||
@@ -0,0 +1,188 @@
|
||||
import math
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
"""
|
||||
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)
|
||||
"""
|
||||
|
||||
def scientific_round(value, uncertainty):
|
||||
"""
|
||||
按照“四舍六入五凑偶”修约:
|
||||
1. 不确定度 u 保留一位有效数字
|
||||
2. 平均值末位与 u 对齐
|
||||
"""
|
||||
if uncertainty <= 0:
|
||||
return str(value), "0"
|
||||
|
||||
u_float = float(uncertainty)
|
||||
first_digit_pos = math.floor(math.log10(u_float))
|
||||
prec = Decimal('1e' + str(first_digit_pos))
|
||||
|
||||
u_final = uncertainty.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
val_final = value.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
return val_final, u_final
|
||||
|
||||
def calculate_stats(data_list, delta_inst):
|
||||
"""计算一组数据的平均值、A类、B类及合成不确定度"""
|
||||
n = len(data_list)
|
||||
mean = sum(data_list) / Decimal(n)
|
||||
|
||||
if n > 1:
|
||||
variance = sum((x - mean)**2 for x in data_list) / Decimal(n - 1)
|
||||
s = Decimal(str(math.sqrt(float(variance))))
|
||||
u_a = s / Decimal(str(math.sqrt(n)))
|
||||
else:
|
||||
u_a = Decimal("0")
|
||||
|
||||
u_b = Decimal(delta_inst) / Decimal(str(math.sqrt(3)))
|
||||
u_combined = Decimal(str(math.sqrt(float(u_a**2 + u_b**2))))
|
||||
|
||||
return mean, u_combined
|
||||
|
||||
def input_data_group(name, count, unit=""):
|
||||
"""输入一组重复测量的数值"""
|
||||
print(f"\n请输入 {name} 的 {count} 次测量值" + (f" (单位: {unit})" if unit else "") + ":")
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
# --- 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()
|
||||
@@ -0,0 +1,201 @@
|
||||
import math
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
"""
|
||||
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)
|
||||
"""
|
||||
|
||||
def scientific_round(value, uncertainty):
|
||||
"""
|
||||
按照“四舍六入五凑偶”修约:
|
||||
1. 不确定度 u 保留一位有效数字(若首位是1或2,有时保留两位,此处统一保留一位)
|
||||
2. 平均值末位与 u 对齐
|
||||
"""
|
||||
if uncertainty <= 0:
|
||||
return str(value), "0"
|
||||
|
||||
u_float = float(uncertainty)
|
||||
# 找到第一位非零数字的位置
|
||||
first_digit_pos = math.floor(math.log10(u_float))
|
||||
prec = Decimal('1e' + str(first_digit_pos))
|
||||
|
||||
# 不确定度修约
|
||||
u_final = uncertainty.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
# 平均值修约,保持与不确定度末位对齐
|
||||
val_final = value.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
return val_final, u_final
|
||||
|
||||
def calculate_stats(data_list, delta_inst):
|
||||
"""计算一组数据的平均值、A类、B类及合成不确定度"""
|
||||
n = len(data_list)
|
||||
mean = sum(data_list) / Decimal(n)
|
||||
|
||||
# A类不确定度
|
||||
if n > 1:
|
||||
variance = sum((x - mean)**2 for x in data_list) / Decimal(n - 1)
|
||||
s = Decimal(str(math.sqrt(float(variance))))
|
||||
u_a = s / Decimal(str(math.sqrt(n)))
|
||||
else:
|
||||
u_a = Decimal("0")
|
||||
|
||||
# B类不确定度
|
||||
u_b = Decimal(delta_inst) / Decimal(str(math.sqrt(3)))
|
||||
|
||||
# 合成
|
||||
u_combined = Decimal(str(math.sqrt(float(u_a**2 + u_b**2))))
|
||||
|
||||
return mean, u_combined
|
||||
|
||||
def input_data_group(name, count, unit="mm"):
|
||||
"""输入一组重复测量的数值"""
|
||||
print(f"\n请输入 {name} 的 {count} 次测量值 (单位: {unit}):")
|
||||
data = []
|
||||
for i in range(count):
|
||||
while True:
|
||||
try:
|
||||
val = input(f"{name}_{i+1} = ").strip()
|
||||
if not val: continue
|
||||
data.append(Decimal(val))
|
||||
break
|
||||
except Exception:
|
||||
print("输入无效,请输入数字。")
|
||||
return data
|
||||
|
||||
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)
|
||||
D_mean, D_u = calculate_stats(D_vals, delta_D)
|
||||
d_mean, d_u = calculate_stats(d_vals, delta_d)
|
||||
b_mean, b_u = calculate_stats(b_vals, delta_b)
|
||||
|
||||
# --- 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()
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,130 @@
|
||||
import math
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
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
|
||||
|
||||
# 进位处理:如果 m 由于位宽限制进位到 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}'"
|
||||
|
||||
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))
|
||||
|
||||
# 修约
|
||||
u_final = u_minutes.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
mean_final_val = mean_minutes.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
# 转换为角度字符串输出
|
||||
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}")
|
||||
@@ -0,0 +1,78 @@
|
||||
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 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 对齐
|
||||
"""
|
||||
u_float = float(u)
|
||||
# 找到第一位非零数字的位置
|
||||
first_digit_pos = math.floor(math.log10(u_float))
|
||||
prec = Decimal('1e' + str(first_digit_pos))
|
||||
|
||||
# 修改:不确定度 u 的修约改为 ROUND_HALF_EVEN
|
||||
u_final = u.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
# 修改:平均值修约保持一致
|
||||
mean_final = mean.quantize(prec, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
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))
|
||||
Reference in New Issue
Block a user