☰
电气元件选型软件:三层建模、计算内核与元件库工程化避坑
2026/10/26 23:59:02 网站建设 项目流程

简介:面向电气设计与建筑配电场景的元件选型辅助工具,适合电气工程师、施工图设计人员及需要快速核算电缆参数的初学者使用。软件围绕电缆线径与载流量计算展开,内置计算模型可结合电流负载、电压等级、敷设方式、环境温度与绝缘材料等因素给出参考结果,并提供元件数据库查询、方案比较与报告生成等功能,帮助减少手工查表带来的误差。压缩包共4个文件,以可执行程序和数据库文件为主,辅以网页说明与文本自述,整体约3.37MB,体积轻便,便于在本地运行和查阅。已有4734人学习,说明其在选型核算场景中具有一定参考价值。读者可借助软件梳理线径选择与载流量校核思路,快速获得计算依据并整理成报告,也可通过内置数据了解不同品牌规格元件的参数差异,为电气系统配置与安全校核提供辅助。

1. 从一张手填的选型表说起:电气元件选型为什么要做成软件

去年帮一个做厂房改造的团队看图纸,配电箱的选型表是手填的:回路号、功率、断路器型号、电缆截面,四列对得整整齐齐,问题出在第七个回路——电缆截面是从上一版复制过来忘了改。这种错人眼很难抓,因为它看起来“合理”。电气元件选型工具软件要解决的就是这件事:把计算电流、断路器整定、载流量校正、电压降、灵敏度校验串成一条固定链路,让每个输出都能倒推回输入。它不适合只想翻样本查两个参数的人,适合手里压着一批回路、要反复算还要出选型清单和 BOM 的人。下面按一套可复现的结构拆:数据怎么建模、内核怎么算、库怎么管、哪里会翻车。

2. 把选型拆成三层:负载模型、元件库、规则表

很多人第一版会写成“输入功率 → 输出型号”的黑匣子,跑十来个回路没问题,跑到第三十个就崩了:因为中间那些判断(系数怎么取、曲线选 B 还是 C、上下级差几档)全散在 if-else 里,改一处要动十处。稍微稳一点的做法是拆三层:负载层只管描述工况,元件库只管描述产品能力,规则层只管描述“什么条件下选什么”。三层之间用数据说话,不互相调用函数。

2.1 负载侧字段的最小闭包

负载模型不是字段越多越好,而是“少一个就算不出来,多一个就没人愿意填”。我用下来最小闭包是下面这些,缺任何一个都会导致后面某条校验失效:

字段类型缺了会怎样
回路编号 tag字符串结果无法回填图纸
额定功率 pn_kw浮点一切计算无从谈起
功率因数 cos_phi浮点计算电流偏大或偏小 10% 以上
效率 efficiency浮点电动机回路电流被低估
相数 phase1 / 3公式直接用错
额定电压 voltage_v220 / 380同上
需要系数 kx浮点干线选型整体偏保守或偏冒险
启动方式 start_mode枚举启动压降和瞬时整定没法校验
电缆长度 cable_len_m浮点电压降算不出来
敷设方式 install枚举载流量基准表选错

这里有两个容易被新手忽略的点。一是效率:电动机铭牌上的功率是轴功率,输入电功率要除以效率,很多人图省事填 1.0,22 kW 的电机算出来电流能差 3% 到 5%。二是需要系数的作用域:它属于“用电设备组”,不属于单台设备,把它挂在每个回路上算完再相加,和平常在干线上乘一次同时系数,结果能差出 20%。我的处理办法是回路级只填设备参数,需要系数和同时系数放在“配电层级”这个对象上,一个层级一份,算干线时统一取。

from dataclasses import dataclass @dataclass class Load: tag: str # 回路编号,例:AP1-07 pn_kw: float # 设备额定功率(轴功率) cos_phi: float # 功率因数 efficiency: float # 效率,电阻性负载填 1.0 phase: int # 1 或 3 voltage_v: float # 220 / 380 kx: float = 1.0 # 需要系数,仅单机回路用 1.0 start_mode: str = "DOL" # DOL 直接启动 / YD 星三角 / VFD 变频 / SOFT 软启 start_multiple: float = 6.0 # 启动电流倍数,变频填 1.5 左右 cable_len_m: float = 30.0 install: str = "tray" # tray 桥架 / conduit 穿管 / buried 埋地 @dataclass class Condition: ambient_c: float = 40.0 # 环境温度 group_count: int = 1 # 同槽并列回路数 soil_rho: float = 2.5 # 土壤热阻系数,埋地才用 harmonic_pct: float = 0.0 # 三次谐波含有率 allowed_dv_pct: float = 5.0 # 末端允许电压降百分比

start_multiple单独拎出来是有原因的:同样是 30 kW,直接启动和变频启动在校验里完全走两条路,前者要卡启动压降和瞬时脱扣躲过启动电流,后者基本不用管这两条。把它做成字段而不是硬编码常量,后面规则表才能按启动方式分叉。

2.2 元件库不是产品目录的复制粘贴

第一版我直接把厂方样本的表格粘进 Excel 导库,结果翻车翻得很彻底:样本上的载流量是“基准工况”下的值(空气 30℃、单回路、桥架),软件里当成了通用值用,夏天车间 45℃ 的时候截面全部偏小一档。正确做法是库里只存基准值和基准条件,校正走系数表,两者分开维护。

另一个常见错误是把分断能力只存一个字段。样本上Icu和Ics是两个数,前者是极限分断能力,后者是运行分断能力,选型要用Icu去比安装点的最大短路电流,但一些老工程师口头说的“分断能力”其实指的是Ics。库里两个都存,界面上标清楚,能省掉大量返工解释。

我这边的字段清单大致如下,实际项目可以按需裁剪,但前八列别省:

列名说明约束
id主键自增
categorymccb / mcb / fuse / contactor / cable枚举
mfr_code厂商代号,不写全称字符串
series系列代号字符串
model完整型号唯一
poles极数1 / 2 / 3 / 4
in_a额定电流> 0
icu_ka极限分断能力≥ in_a 对应档位
ics_ka运行分断能力≤ icu_ka
curveB / C / D / MA断路器才有
frame壳架等级塑壳才有
base_temp_c载流量基准温度电缆才有
base_amp基准载流量电缆才有
statusactive / eol停产品牌置 eol

status这个字段是血泪经验:老项目维护时会拿几年前的选型单来对,如果库里只有 active 的元件,历史项目一打开就全是“找不到型号”。留一个 eol(停产)状态,历史单能正常显示,新项目选型时过滤掉,两头都不耽误。

2.3 规则表:把老工程师的判断做成可覆盖的配置

规则层最容易写歪。有人把它写成一大堆if kx > 0.8 and pn > 30 and ...,跑起来是对的,但没人敢改。我的做法是把判断写成“条件 → 动作”的 JSON,条件用字段名加比较符表达,动作只做三件事:调整下限、切换分支、加备注。

RULES = [ {"id": "MOTOR_D_CURVE", "when": {"category": "mcb", "start_mode": "DOL"}, "do": {"curve": "D", "note": "直接启动电动机,瞬时脱扣需躲过启动电流"}}, {"id": "LIGHT_C_CURVE", "when": {"category": "mcb", "load_type": "lighting"}, "do": {"curve": "C", "note": "照明回路"}}, {"id": "HARMONIC_UP", "when": {"harmonic_pct": {">": 15}}, "do": {"ampacity_factor": 0.86, "note": "三次谐波超 15%,中性线按相线放大"}}, {"id": "BIG_MOTOR_CHECK", "when": {"pn_kw": {">=": 30}, "start_mode": "DOL"}, "do": {"require": ["start_dv_check"], "note": "大功率直接启动必须校验启动压降"}}, ]

这套结构的价值在于可解释。每个输出结果都能带一条 note 说明“为什么选 D 曲线”,出图时打在选型卡上,审核的人不用来问。规则命中的顺序也要定死:先按类别过滤,再按负载类型分叉,最后叠加环境修正,顺序乱了会出现同一条回路两次改同一个字段,后一次悄悄覆盖前一次。

2.4 候选筛选的最小可跑实现

有了三层,筛选就退化成一次查询加一次内存过滤。查询负责把不可能的型号干掉,内存负责规则。

import sqlite3 def fetch_candidates(conn, category: str, poles: int, min_in: float, min_icu_ka: float, limit: int = 20): """按硬性条件粗筛,返回按额定电流升序的候选。""" sql = """ SELECT id, model, in_a, icu_ka, ics_ka, curve, frame FROM component WHERE category = ? -- 元件类别 AND poles = ? -- 极数必须匹配 AND in_a >= ? -- 额定电流下限,由计算电流推导 AND icu_ka >= ? -- 分断能力下限,由安装点短路电流推导 AND status = 'active' -- 停产品牌不进新选型 ORDER BY in_a ASC, icu_ka ASC LIMIT ? """ return conn.execute(sql, (category, poles, min_in, min_icu_ka, limit)).fetchall()

min_in不要直接传计算电流,要传“计算电流 × 一个余量系数”,这个系数放规则表里,不同行业取值不同,硬编码在函数里以后改一次要重新发版。LIMIT也别省,候选太多界面会卡,正常回路取前 20 个足够覆盖到合适档位,真需要大档位的场合说明前面的条件填错了。

3. 计算内核:从计算电流到断路器、电缆的整条链路

内核部分最怕“算得对但顺序错”。正确顺序是先算电流,再定断路器额定值,再用断路器额定值反推电缆截面,最后回头校验电缆和断路器是否互相保护。顺序颠倒的典型表现是:先按电流选电缆,再选断路器,结果断路器额定值比电缆允许载流量还大,电缆过载时断路器不跳。

3.1 计算电流与需要系数法:三个最容易填错的入参

三相和单相的公式只差一个系数,但填错的频率高得离谱。写成两个分支,别用“除以根号三再判断”这种精简写法。

import math def calc_current(pn_kw: float, cos_phi: float, eff: float, phase: int, u: float, kx: float = 1.0) -> float: """返回计算电流 Ib,单位 A。""" if cos_phi <= 0 or eff <= 0: raise ValueError("功率因数和效率必须大于 0") p_in = pn_kw * 1000 * kx # 折算到输入电功率 if phase == 3: return p_in / (math.sqrt(3) * u * cos_phi * eff) return p_in / (u * cos_phi * eff) # 单相,u 填 220

三个入参要盯死。cos_phi很多人填的是补偿后的目标值,但选进线断路器应该用补偿前的自然功率因数,补偿后的值只影响无功计算。eff上面提过了。kx在单机回路上必须填 1.0,填小了电流被低估,断路器选小,一启动就跳,这种故障现场很难查,因为算出来的表格“看起来没问题”。

还有一个隐性坑:焊机、起重设备这类负载的额定值不是连续工作制下的功率,需要按负载持续率折算。软件里我给这类负载加了一个duty_cycle字段,算电流前先把pn_kw乘上sqrt(ε),ε 是负载持续率。这个换算不写进代码注释,半年后没人想得起来为什么结果和手算对不上。

3.2 断路器:额定电流、分断能力与灵敏度校验

断路器要过四道关,少一道都不算选完:

  1. Ib ≤ In:计算电流不超过断路器额定电流;
  2. In ≤ Iz:断路器额定电流不超过电缆允许载流量;
  3. Icu ≥ Ik_max:分断能力不小于安装点最大三相短路电流;
  4. Ik_min ≥ 1.3 × Ii:末端最小短路电流不小于瞬时整定值的 1.3 倍,保证单相接地能跳闸。

第二条和第四条是最常被跳过的。第一条谁都会算,第三条看图纸上的短路电流表,第二条要等电缆选完才能校验,第四条需要算末端单相短路电流——很多人干脆不算,结果就是现场“断路器不跳、电缆先糊”。灵敏度这一条尤其麻烦,长距离小截面回路的末端短路电流可能只有几百安,而 C 曲线 16 A 的瞬时整定是 160 A,看似够,但如果上级是 63 A 的 C 曲线,瞬时整定 630 A,末端故障就只能靠过载长延时慢慢烤。

提示:灵敏度校验用的是“最小短路电流”,不是最大。最大短路电流用于选分断能力,最小短路电流用于校核脱扣,两个数混用是典型错误。

工程上常见做法是给灵敏度留 1.3 倍余量,也有按 1.2 倍卡的,软件里做成可配置参数,默认 1.3,特殊行业可以调。整定值的取法也别写死:塑壳断路器有热磁和电子两套,电子脱扣的Ir是连续可调的,热磁的只有固定档位,库里要存“可调范围”而不只是“额定值”,否则算出来的整定值在实物上调不出来。

3.3 电缆截面:载流量校正与电压降的双约束

电缆是整条链路里唯一有两个独立约束的元件:热约束(载流量)和电压约束(电压降)。两个都过才算过,只过一个是常见事故来源。

载流量校正的公式简单,难的是系数表要跟基准条件对齐:

# 环境温度校正系数,基准 30℃ TEMP_K = { ("xlpe", 30): 1.00, ("xlpe", 35): 0.96, ("xlpe", 40): 0.91, ("xlpe", 45): 0.87, ("xlpe", 50): 0.82, ("pvc", 30): 1.00, ("pvc", 35): 0.94, ("pvc", 40): 0.87, ("pvc", 45): 0.79, ("pvc", 50): 0.71, } # 并列敷设校正系数,按同槽回路数 GROUP_K = {1: 1.00, 2: 0.80, 3: 0.70, 4: 0.65, 6: 0.57} def ampacity(section: float, base_table: dict, insulation: str, ambient_c: float, groups: int) -> float: """返回校正后的允许载流量 Iz,单位 A。""" it = base_table[section] # 基准载流量 k1 = TEMP_K[(insulation, int(ambient_c))] # 温度校正 k2 = GROUP_K[min(groups, 6)] # 并列校正 return it * k1 * k2

base_table是每种截面在基准工况下的载流量,必须和TEMP_K的基准温度一致。我见过一个版本,载流量表是从 40℃ 的样本页抄的,温度校正表按 30℃ 基准写的,40℃ 环境下等于校正了两次,截面直接放大两档,材料费多出一截还没人发现。

电压降用下面这个工程近似,够用且好解释:

R20 = {1.5: 12.1, 2.5: 7.41, 4: 4.61, 6: 3.08, 10: 1.83, 16: 1.15, 25: 0.727, 35: 0.524, 50: 0.387} # 铜芯 Ω/km,20℃ X_PER_KM = 0.08 # 感抗工程近似 Ω/km def voltage_drop_pct(ib: float, length_m: float, section: float, cos_phi: float, u: float, phase: int = 3) -> float: r = R20[section] * 1.2 # 折算到工作温度 sin_phi = math.sqrt(max(0.0, 1 - cos_phi ** 2)) z = r * cos_phi + X_PER_KM * sin_phi # Ω/km du = math.sqrt(3) * ib * (length_m / 1000) * z if phase == 1: du = 2 * ib * (length_m / 1000) * z # 单相往返,去掉根号三 return du / u * 100

1.2这个温度折算系数是经验值,铜芯从 20℃ 折算到 70℃ 附近差不多是这个量级,想要更准就按导体电阻温度系数算,但工程上差别不到 3%,用常数更好解释。单相回路别忘乘 2,忘乘的话 50 米以外的回路电压降会被低估一半,这种错在照明回路上特别隐蔽——灯能亮,就是末端偏暗。

3.4 把四道校验串成一个函数

单点计算写完了,串起来才有意义。函数返回结构里带上失败原因,比返回一个 None 有用得多。

def select_feeder(load: Load, cond: Condition, cable_table: dict, breakers: list, rho: float = 0.0175) -> dict: ib = calc_current(load.pn_kw, load.cos_phi, load.efficiency, load.phase, load.voltage_v, load.kx) in_min = ib * 1.1 # 断路器额定电流下限 for br in breakers: # breakers 已按 in_a 升序 if br["in_a"] < in_min: continue if br["icu_ka"] < cond.short_circuit_ka: continue # 用断路器额定值反推电缆最小截面 for sec in sorted(cable_table): iz = ampacity(sec, cable_table, cond.insulation, cond.ambient_c, cond.group_count) if iz < br["in_a"]: continue dv = voltage_drop_pct(ib, load.cable_len_m, sec, load.cos_phi, load.voltage_v, load.phase) if dv > cond.allowed_dv_pct: continue return {"breaker": br["model"], "cable_mm2": sec, "ib": round(ib, 1), "iz": round(iz, 1), "dv_pct": round(dv, 2), "reason": "ok"} return {"reason": "no_match", "ib": round(ib, 1)}

注意breakers必须预先排好序,函数里靠顺序表达“从小到大试”,比每次排序省事也更好读。返回reason是为后面批量跑做准备:一百条回路里有多少条是no_match、多少条是电压降卡住,聚类一下就知道是数据问题还是参数问题。

4. 元件库工程化:CSV 到 SQLite 的导入、字段约束与版本比对

选型软件真正的门槛不在算法,在库。算法三个月能写稳,库要维护好几年。我见过几个自研工具最后没人用,原因都是“库里型号不全”或者“库里型号是两年前的”。

4.1 三张核心表就够

别一上来搞七八张表,先用三张跑通:

表名作用关键列
component元件主数据model、category、in_a、icu_ka、curve、status
cable_spec电缆基准载流量section、insulation、cores、base_temp_c、base_amp
rule选型规则rule_id、condition_json、action_json、enabled

component和cable_spec分开是有必要的,因为电缆的载流量取决于芯数、绝缘、敷设方式三个维度,硬塞进主表会变成一堆带后缀的列。rule单独一张表的好处是现场能改——调试阶段经常要临时放宽某个系数,改表比改代码快得多,改完留下记录,事后能追溯是谁在什么时候动过。

表结构定下来之后,索引要跟上:component在(category, poles, in_a)上建联合索引,筛选查询基本都走这个组合;cable_spec在(section, insulation)上建唯一索引,防止同一个截面被导两次。

4.2 导入脚本:把脏数据挡在门外

厂方样本转成 CSV 之后,脏数据的花样比想象中多:全角数字、单位写在数值里(“16A”)、空行、合并单元格导出的重复行、Ics大于Icu的录入错误。导入脚本必须逐行校验并且报行号,不能静默跳过。

import csv, sqlite3 REQUIRED = ["model", "category", "poles", "in_a", "icu_ka", "ics_ka"] ALLOWED_CATEGORY = {"mccb", "mcb", "fuse", "contactor"} def import_components(path: str, conn: sqlite3.Connection) -> list: bad = [] with open(path, newline="", encoding="utf-8-sig") as f: for ln, row in enumerate(csv.DictReader(f), start=2): miss = [k for k in REQUIRED if not (row.get(k) or "").strip()] if miss: bad.append((ln, "缺字段:" + ",".join(miss))) continue try: in_a = float(row["in_a"]) icu = float(row["icu_ka"]) ics = float(row["ics_ka"]) except ValueError: bad.append((ln, "数值解析失败")) continue if row["category"] not in ALLOWED_CATEGORY: bad.append((ln, f"未知类别 {row['category']}")) continue if ics > icu: bad.append((ln, f"Ics({ics}) 大于 Icu({icu}),疑似录错列")) continue if in_a <= 0 or icu <= 0: bad.append((ln, "额定值必须为正")) continue conn.execute( "INSERT OR REPLACE INTO component" "(model, category, mfr_code, series, poles, in_a, icu_ka," " ics_ka, curve, status) VALUES (?,?,?,?,?,?,?,?,?,'active')", (row["model"].strip(), row["category"], row.get("mfr_code", ""), row.get("series", ""), int(row["poles"]), in_a, icu, ics, row.get("curve", "").strip().upper())) conn.commit() return bad

INSERT OR REPLACE是给重复导入用的,同一个型号再导一次会覆盖而不是报错,配合model的唯一约束正好。bad列表返回给界面显示,行号是关键——让录入的人自己去看第几行,比让他翻整份 CSV 快十倍。校验里Ics > Icu这条看着多余,实际抓到过好几次,属于典型的列错位。

单位也要在导入时统一。有些样本用 kA,有些用 A,混着进库之后icu_ka字段里出现 50000 这种值,筛选条件全乱。我的做法是脚本里所有电流统一成 A,界面上再按量级格式化显示,存和显分开。

4.3 版本比对:样本换版后哪些回路要重算

库更新之后最麻烦的问题不是“新数据进没进去”,而是“老项目要不要重算”。做法是给每次导入打一个dataset_version,元件行上记版本号,再写一条比对 SQL:

-- 找出同一型号在新旧版本之间关键参数发生变化的记录 SELECT n.model, o.in_a AS old_in, n.in_a AS new_in, o.icu_ka AS old_icu, n.icu_ka AS new_icu FROM component n JOIN component o ON n.model = o.model WHERE n.dataset_version = :new_ver AND o.dataset_version = :old_ver AND (n.in_a <> o.in_a OR n.icu_ka <> o.icu_ka);

结果里new_in > old_in的型号要重点关注:原来选这个型号的回路,计算电流可能已经超过新的额定值,属于必须重算的集合。反过来new_icu < old_icu的要检查分断能力是否还够。这套比对跑一次只要几秒,但能避免“库更新了、图纸没更新”这种最难查的问题。

版本号别用日期,用递增整数加一个备注字段。日期看着直观,一旦一天导两次就分不清先后,递增整数加备注既唯一又能写清楚“这次加了哪几个系列”。

5. 避坑与排查:五条在真实回路里翻车的记录

下面这五条基本覆盖了我在不同项目里踩过的坑,每条都按“现象 → 原因 → 解决”写,能对上号的直接照着改。

5.1 需要系数被当成“打折”

现象:一批风机回路算出来的电流比铭牌电流还小,选出来的断路器现场一启动就跳,换成大一档才好。 原因:把需要系数kx填在了单机回路上,填了 0.7,等于把额定电流打了七折。需要系数是给用电设备组做统计用的,单台设备的电流就是额定电流。 解决:数据结构上把kx从Load挪到“配电层级”对象,单机回路的计算函数强制传 1.0,并在界面上把这一项置灰。物理上不可能的东西,靠界面拦住比靠人记住更可靠。

5.2 电压降算对了,启动压降没算

现象:45 kW 水泵回路,正常运行时末端电压降 3.2%,符合要求,但一启动接触器就抖,有时直接跳闸。 原因:只算了稳态电压降,没算启动瞬间的压降。直接启动的启动电流是额定电流的 6 倍左右,同样的线路阻抗下压降也放大 6 倍,端子电压掉到 80% 以下,接触器线圈吸不住。 解决:给start_mode为 DOL 或 YD 的回路加一条启动压降校验,用启动电流替代计算电流重跑一遍voltage_drop_pct,按端子电压不低于 80%(频繁启动按 85%)卡。不通过就提示放大截面或改软启动,而不是等现场出事。

5.3 载流量表的基准温度不一致

现象:同一份图纸,两个人用同一个软件算出来的电缆截面差一档,谁也说服不了谁。 原因:库里这份载流量表是从 40℃ 环境下的样本页抄的,而温度校正表的基准是 30℃,等于对 40℃ 环境校正了两次。第二个人的环境温度填了 35℃,差异就显现出来了。 解决:cable_spec表强制带base_temp_c字段,导入时校验同一批数据的基准温度必须一致,不一致直接拒绝。校正函数里也断言ambient_c >= base_temp_c才做降容,低于基准温度时给 1.0 而不是放大。

5.4 分断能力填的是 Ics 不是 Icu

现象:短路电流计算书上是 36 kA,库里筛出来的断路器标着 36 kA,装上去之后上级跳了、这只没跳,触头烧蚀。 原因:库里存的 36 kA 是Ics(运行分断能力),Icu只有 25 kA。选型要比的是Icu,用Ics去比等于放宽了要求。 解决:两个字段都存、都显示,筛选条件写死用icu_ka,ics_ka只用于展示和校验ics ≤ icu。界面上的字段标签写全称,别只写“分断能力”三个字。

5.5 默认值静默覆盖手工修改

现象:工程师手工把某条回路的曲线从 C 改成 D,保存后重新打开又变回 C。 原因:规则表每次加载都会重算一遍并写回结果字段,手工修改和规则输出共用同一个字段,规则后执行就覆盖了。 解决:结果表拆成auto_value和manual_value两列,最终取值优先manual_value,界面上标一个“已手工调整”的小标记。规则重算只写auto_value,永远不碰手工列。这个改动很小,但它是这类工具能不能被老工程师接受的分水岭——没人愿意用一个会偷偷改掉自己判断的软件。

6. 复核闭环:用回归用例把选型结果钉住

算法改一次就要担心一次,这是所有自研选型工具的通病。解决办法不复杂:攒一批典型回路当回归集,每次改代码、换库版本都跑一遍,把结果和不通过原因一起打出来。我这边的回归集常年保持在二十条上下,覆盖直接启动的大电机、长距离照明、谐波较大的 UPS 回路、埋地敷设、并联多回路这几种边界。

用例关键参数期望结果
C01 大电机直启45 kW,DOL,60 m触发启动压降校验并给出放大截面建议
C02 长距离照明3 kW,单相,120 m电压降卡住,截面大于载流量所需
C03 谐波回路三次谐波 22%中性线放大,载流量系数 0.86
C04 并联六回路桥架六回路并列校正系数 0.57,截面升两档
C05 埋地敷设土壤热阻 3.0走埋地基准表,不套空气温度系数

跑回归的脚本不长,关键是把失败原因归类,而不是只报“不通过”:

def run_regression(cases, engine): stat = {} for c in cases: r = engine(c["load"], c["cond"]) # 复用第 3 章的内核 ok = (r["reason"] == "ok" and c["expect_cable"] <= r.get("cable_mm2", 0)) key = r["reason"] if r["reason"] != "ok" else "pass" stat.setdefault(key, []).append(c["id"]) if not ok: print(f"[FAIL] {c['id']} ib={r['ib']} " f"cable={r.get('cable_mm2')} expect>={c['expect_cable']}") for k, v in stat.items(): print(f"{k}: {len(v)} 条 -> {','.join(v)}") return stat

expect_cable是人工确认过的下限值,不是精确值。用“不小于”而不是“等于”,是因为库里加几个新型号就会改变候选顺序,卡精确值会天天误报。真正要盯的是reason的分布:如果某次改动之后no_match从 1 条涨到 6 条,基本可以确定是新导入的库有问题,而不是算法退化。

engine这一层建议做成纯函数,输入Load和Condition,输出字典,不碰数据库连接。回归时把库一次性读进内存传给函数,跑二十条用例不到一秒;如果每条用例都去连库,光 IO 就把时间耗完了,没人愿意在提交前跑。

从那以后我每次换库版本、改任何一条规则,都强制把这二十条回归用例跑一遍再看 diff,哪怕只改了一个系数。吃过一次亏:为了赶时间跳过了回归,结果温度校正表被误改,一批夏季工况的回路截面集体偏小一档,图纸发出去两周才被发现。希望帮到你——如果你正在做类似的工具,先把这三层结构和这批回归用例立起来,剩下的慢慢补。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询