杂记 › 技术笔记 › 粘贴 100 行分数,第 45 行被悄悄算成 1/4:约分这页的负号、空行和大数各归谁管

粘贴 100 行分数,第 45 行被悄悄算成 1/4:约分这页的负号、空行和大数各归谁管

100 行分数里掺了 5 行错的,页面只报 4 行:带分数被静默算成另一个数,负号统一搬到分子,大数在解析那一步就换成浮点。

第 45 行那个带分数,被算成了另一个数

把一批分数练习整列粘进约分页的批量框,100 行进去、100 行出来,逐行核对才发现第 45 行不对。我写的是一又四分之三,串是 1 3/4,页面回的是「第45行1/4 = 1/4 (0.25)」——它没报错,只是把整道题换成了另一个数。原因在解析那一步:批量走第 167 行,先按半角斜杠切两段,再把两头交给 parseInt,而这个函数读到空格就停。于是 2 1/2 得 1,1+3/4 同得 1/4,1.5/2 得 1/2。真正会报错的是另一类:3/4/5、0.75、还有用全角斜杠写的 1/4,都判「格式错误」。

区分这两类很要紧。报错的行你一眼就看得见,静默改值的行穿着正常结果的外衣混在批量的红字之外——100 行里掺的 5 行只有 4 行被判错(「格式错误」3 次加「分母为0」1 次),剩下那行正是改了值的带分数。

负号只有一个家,分母那边永远不留

约分页的模板在第 81 行做了一次翻号:负号只往分子上搬,搬完分母侧恒为正。所以 -3/4 和 3/-4 都输出 -3/4,-3/-4 输出 3/4。批量那侧还有个额外动作,第 178 行把结果重拼成「原文 → 最简」的形态,于是原文里的空格与负号会被照抄回去再补上落点,写成 3 / -4 的行回显成 3/-4 → -3/4。

负零也不用担心。输入 -0/5 与 0/-5,最简、等值小数、百分比、约分倍数这 4 个出口给出的依次是 0、0、0.00%、1/5,页面上任何一条路径都不会留下字面的负零,因为 String 把负零写成 0。

分母为 0 根本轮不到求公约数

这一页把除零拦在上游:单条在第 123 行判掉、第 125 行给出「分母不能为 0」这句提示,批量在第 173 行给「分母为0」。同一条路径、同一句文案覆盖了 0/0、5/0、5/-0、5/0.0 这几种写法,而第 80 行与第 86 行里那两处针对分母为零的分支,在界面上其实走不到。还有一种更绕的命中:0b11/0b100 也被判分母为 0,因为 parseInt 不认二进制前缀,两头都读成 0。

批量的行是 1:1 的,行号却不是

100 行进去是 100 条结果,textarea 里那 598 字符一条不丢,失败的行也按原位插成红字,整批不中断——第 166-183 行的循环里那 3 处提前返回只跳过当前行。输出片段量了一下是 22167 字符、22727 字节。可第 165 行那个 validCount 被读取 0 次,页面上没有任何行数或成功数的汇总,你得自己数。

行号还是重排过的:8 个物理行里含 4 个空行,只渲染 4 条,物理第 8 行那道 24/36 被标成「第4行」。换行方面 CRLF 由第 156 行的 trim 兜住,3 条正常;裸回车把 3/6 与 4/8 连起来时,整串被当 1 行报格式错误。

写法这一页怎么处理批量里的回显
1 3/4空格处截断,静默改值第45行1/4 = 1/4 (0.25)
3/4/5切出三段,判非法格式错误
5/-0上游拦截,不进求公约数分母为0
9007199254740993/6先折成 double 再约4503599627370496/3

单条那两个框是 number 类型

粘贴 +3、1/1、0x10 甚至 ½ 进分子框,浏览器的净化发生在 parseInt 之前,整框被清成空串,第 121 行的 isNaN 直接 return,两张卡都不显示、错误栏是空字符串——连一句报错都没有。逐字敲进去更坑:3/4 被吞成 34、0x10 被吞成 010 之后照样算,得数栏一路算到 5/2。

等值小数没有循环节,只有一条 14 字符门槛

第 89 行的判据是把除法结果转成字符串后看长度是否大于 14,命中就用 toFixed(10) 再补三个点。于是 1/3 显示成 0.3333333333...、1/6 显示成 0.1666666667...(末位是进位来的)、1/999 显示成 0.0010010010...。反过来,能除尽的 1/8192 因为结果有 15 字符也被砍成 10 位,而 1/4096 正好 14 字符,原样留着。分数之间要接着算,分数运算那类入口给的是通分后的精确结果;只想看小数位数,交给小数格式化按位裁更直接。

大数在 parseInt 那一步就换成了浮点

模板里 BigInt 出现 0 次,第 113/114 行和第 167 行的 parseInt 把长串折成 double,超出安全整数就丢尾数。实测 9007199254740993/6 这一题,页面给 4503599627370496/3,按整数真值算是 3002399751580331/2,差 -0.166666…;999999999999999999/3 更别扭,页面判定它已是最简并回显 1000000000000000000/3,真值是 333333333333333333,差 +0.333333…。还有两种写法会走偏:1e21/3 的 parseInt 在第 1 个字符 e 处停读,整题变成 1/3;相邻的两个大整数 9007199254740993/9007199254740992 被折成同一个数,直接输出整数 1。

输入串9007199254740993/6页面输出4503599627370496/3整数真值3002399751580331/2两者相差-0.166666…

图 1:同一道题在 parseInt 前后各是什么,尾数在哪一步改掉,差额就出现在哪一行。

位数再往上就形态都保不住:12345678901234567891/2 得 6172839450617284000,与真值差 -361.5;200 位分子的串先被折成 1.2345678901234567e+199,最简栏直接输出 6.172839450617284e+198/3,百分比栏给 2.0576131502057615e+200%,分数在这一栏已经不成其为了。

常见问题

Q:批量结果里怎么分辨哪行被静默改了值?

看原文那一段。第 178 行会把输入原样回显再补结果,所以 1 3/4 这类会显示成「1/4 = 1/4」——等号左边已经没有你写的那个数了。页面不给汇总,只能逐行比。

Q:带分数到底能不能写?

这一页只认两段式:分子、分母各一段,第 75-78 行的输出也只有整数与分数两种形态,7/1 会显示成 7。要输入一又四分之三,先自己换算成 7/4 再粘。

Q:超过 16 位的分子分母该怎么约?

别指望这一页,它在解析阶段就转成浮点了,实测连判「已最简」都会看错。要么先把数拆小,要么用支持任意精度的整数运算环境。

📎 相关文章

把 3. 起步贴进 Markdown 转 HTML,为什么有序列表的编号只认第一个数 2026-11-03 文本切成 43 片再拼回去少了 42 个字节,切口其实都落在换行上 2026-11-03 Crontab 表达式 0 0 13 * 5 到底哪天跑:这一页只排 2 次,真实 cron 是 62 次 2026-11-03 16 组开关实测 HTML 去标签:报 19 个标签,实际删掉 148 个字符 2026-10-30 SVG 转 PNG 后外链图丢了一半:同一份 594 B 文件预览有 3 张图、成品只剩 1 张 2026-10-30