空一个框,可见卡片就成了 0 张
这个页面的输入是分子、分母两栏一行的网格,默认三行 1/2、1/3、1/4。先让它算成功,再把任意一个框整个清空,露出来的输出卡片还剩几张?四组清空方式答案一样:0 张——没有结果卡,也没有错误卡,错误文案是个空串。
计算函数一进来就把结果卡和异常卡都置成 display:none,再逐行 parseInt;只要有一个框解析出 NaN 就直接 return,那两行 display 再也没被改回来。失败在这里不是走一条提示分支,而是退回两张卡都藏着的初始状态。
| 输入状态 | 可见卡片 | 错误文案 |
|---|---|---|
| 3 行页清掉第 1 行分子 | 0 张 | 0 码元 |
| 3 行页第 3 行两个框都清 | 0 张 | 0 码元 |
| 第 2 行分母填 0 | 1 张错误卡 | 20 码元 / 48 字节 |
| 只剩 1 行且两框都空 | 1 张错误卡 | 15 码元 / 39 字节 |
唯一会说话的是分母为 0 那条:文案逐字「⚠️ 第 N 个分数的分母为 0,请修正」,单数字时 20 码元 / 48 字节,N 从 1 数起,第 1、2、3、5 行的分母为 0 分别报 1、2、3、5。而 NaN 与 0 同时在场时,报不报要看行序——空框在第 1 行时函数第 1 行就返回,第 2 行那个 0 完全不提。
图 1:可见卡片张数的对照——空框与 2 行全空都是 0 张
静默那一次,旧结果和旧文案都不清
按步骤走一遍。分数通分计算这页能写入的出口只有 8 个 id:两行 1/2、1/3 算成功,结果区写着「1/2 = 3/6」「1/3 = 2/6」;第 2 行分母改 0,换成 1 张错误卡;再清空第 1 行分子,卡片归 0,而 DOM 一样没清——那句 20 码元的文案仍在、公分母格仍是 6、结果区仍是那 2 行、复制文本仍是 26 码元、过程区还挂着 6 行旧过程。复制按钮写在结果卡内部,卡一藏这份旧文本也就点不到。
parseInt 不带基数:7 个静默、22 个截断
两个框都按 parseInt(value) 读取,没写第二个基数参数。29 个测试串里 7 个给 NaN 走静默那一路——空串、3 个空格、".5"、"abc"、"Infinity"、"NaN"、"½";剩下 22 个全部无声截断。
| "1.5" | "3.9999" | "-1.9" | "1e3" | "0x10" | "08" | "12abc" | "1,5" |
|---|---|---|---|---|---|---|---|
| 1 | 3 | -1 | 1 | 16 | 8 | 12 | 1 |
分母位喂 "1.5" 时公分母是 3,结果行逐字「1/1 = 3/3」「1/3 = 1/3」——页面按 1/1 通分,框里的 1.5 不回写;"1e3" 同样按 1/1 走,一个 1000 被当成 1。浏览器能否把 "0x10"、"12abc" 留在 type=number 的框里本批未实测,能确定的是框值为空串时 parseInt 必给 NaN。
负分母:负号的三种命运
公分母那一侧取绝对值,倍数那一侧带符号。1/2 配 1/-3 那组公分母 6,结果行「1/-3 = -2/6」,过程行写「分母列表: 2, 3」「LCM(2, 3) = 6」——负号在分母列表这行就消失,倍数那行明写「分子分母同乘 -2=-2/6」。三行 1/-2、1/-3、1/-4 给公分母 12、结果 -6/12、-4/12、-3/12。0 乘负倍数得负零、字符串化成 0,于是写「0/-2 = 0/4」;同负的 -2/-3 负负得正,输出「-2/-3 = 10/15」。
链式 LCM,与 990 行不是最简
多个分母的公分母是从 1 起 reduce 的链,折叠次数恒等于分母个数:2、3、4 的中间值走 2、6、12;12、18、30 走 12、36、180,中间那个 36 不是结果的因子;3、5、7、11 给 1155;2、3、5、7、11、13 给 30030。
化简那一步在代码里不存在,全文没有第二次求最大公约数。1/2 与 2/4 同列时公分母 4,输出「1/2 = 2/4」「2/4 = 2/4」,第二条是原分母已等于公分母的恒等行。样本放大到 576 组两行网格、1152 行结果:990 行的新分子与公分母还有公因子、537 组至少一行不是最简、453 组两行都不是、180 组含恒等行;两个原分数都已最简的 289 组里,通分后仍不是最简的有 250 组。这是对输出文本的计数,不是对使用者的建议。
「分数4」和「分数2」是同一行
行标签是「分数」加一个只增不减的计数器,删行不回收编号。首屏 3 行标「分数1、分数2、分数3」,删第 2 行再加 1 行,标签变「分数1、分数3、分数4」——行数还是 3,最大编号已经 4;过程区用的是数组下标,那第三行在过程里被叫作「分数2」。反复加删 20 轮,行数恒为 3、标签跑到「分数21、分数22、分数23」、计数 23;只有「重置」把计数归 0,标签才重新从 1 数到 3。
删行按 cd-row- 拼原始编号找 DOM,找不到就跳过、不报错——对已删那行再点一次行数变化 0,编号 99 同样没动静,可末尾那次重算写在 if 外面,什么都没删成也照样算一遍。加行反过来不算:实测一组行数 4、标签「分数1、分数4、分数5、分数6」,页面仍亮着那句 15 码元的提示,结果卡里留着上一轮的 2 行「1/2 = 2/4」「1/4 = 1/4」和公分母 4。
复制文本的段数是行数加 1
复制取隐藏 span 的 textContent,首行恒为「公分母: 」、之后每条分数一行,所以段数总是行数加 1:2 行 3 段 26 码元、3 行 4 段 40 码元、4 行 5 段 55 码元、8 行 9 段 137 码元、10 行 11 段 193 码元。拼装时每行末尾都各加一个换行,写进去前有一次 trim:41 码元 / 47 字节变 40 码元 / 46 字节,切分段数从 5 变 4,差值恰好 1 码元 / 1 字节;串首是「公」没有前导空白,末字符是数字。12 行分母排到 12 时公分母 27720,第一条写着「1/1 = 27720/27720」。
常见问题
Q:清空一个框,页面为什么什么都不显示?
两张卡在函数开头就被藏掉,解析出 NaN 时直接 return,没有一处再把它们亮回来,所以可见卡片是 0 张;分母填 0 才有那句 20 码元的提示。
Q:结果不是最简分数,是不是算错了?
这一页只做通分那步乘法,输出的是同分母形式,576 组样本里 990 行还有公因子。通分之后怎么接着加减、约分放在事前还是事后,另一篇 分数加减的过程 讲过。
Q:分母很大时会不会出问题?
本页实测到的量级只有 12 行分母排到 12 时那个 27720,更大的输入不在这一页的测量范围里;超大数上最小公倍数的浮点表现,另一篇 先乘后除的中间量 量过。