同一个名字,底下挂着两套系数
食谱里的「add 1 gal」、参数表上的「110 hp」、血压计上的 mmHg、新硬盘拆封少掉的那截容量,麻烦都不在乘法,而在「这个名字是哪一个定义」:系数是确定的,出错的是人选错了系数。模板 unit-convert.html 是 12037 字节、227 行,运行时 10 个类目、110 个单位(长度 15、重量 14、面积 14、体积 14、温度 4、速度 8、时间 12、数据存储 11、压力 10、功率 8),下面四组就在同一类目里并排。
| 量名 | 两种写法与系数 | 实测尾差 |
|---|---|---|
| 体积·加仑 | gal 3.785411784 / gal(UK) 4.54609 | 折成升差 0.7606782160000005 |
| 功率·马力 | hp 745.6998715823 / PS 735.49875 | 折成瓦差 10.201121582300061,大 1.3870%、小 1.3680% |
| 压力·汞柱 | mmHg 133.322387415 / Torr 133.322368421 | 760 高度差 0.000014435440007787292 kPa |
| 存储·字节 | KB 1000 / KiB 1024 | MB 与 MiB 差 48576 B |
加仑差两成,马力差到小数点后第五位
加仑那两行不只是显示值不同:以美制为源时 立方英寸 恰好是 231、加仑(英) 行 0.83267418,以英制为源时 加仑(美) 显示 1.2009499。英制比美制大 20.0950%、美制比英制小 16.7326%,只说「约 20%」会漏掉基准,单位换算也不替你判断食谱里那个 gal 属于哪一种,它只把两边同屏摆出来。
另外两条更细:1 hp 折成 英尺磅每秒 显示 550、原始值却是 550.0000000127599,恒等式并不恰好成立;mmHg 与 Torr 那 0.000014435440007787292 kPa 来自截断——101325 ÷ 760 = 133.32236842105263,代码存成 133.322368421,误差 -5.263700586510822e-11 帕。这一对与其算两种定义,不如算一种定义、两种近似。
图 1|三对同名单位在模板函数里的实测显示值。条形只在同对内按较大值等比,跨对不可比;最后一对差在第 6 位,已经分不出长短。
字节的两套进位:差从 48576 长到 99511627776
数据存储类 11 个单位里,KB 的 1000 与 KiB 的 1024 同时存在。1 MiB 折字节 1,048,576、折 MB 显示 1.048576;1 MB 折字节 1,000,000、折 MiB 0.95367432。差从兆一档的 48576 字节(比值 1.048576)长到吉一档的 73741824(1.073742)、太一档的 99511627776(1.099512),1 TiB 折字节直接显示 1.099512e+12。
这是进位基数之争,跟 2、8、16 那种进制是两件事(要看同一个数换进制的样子得用进制转换),也不等于编码字节数(那归字数与字节统计)。文案里那句「存储容量与网速的 KB/KiB、Mbps 与 MB/s」得改口:这一类全是纯量,模板里 Mbps 与 MB/s 各出现 0 次。
温度不走系数
温度类 4 行没有系数列,公式行固定写着华氏 = 摄氏 × 9 ÷ 5 + 32、开尔文 = 摄氏 + 273.15,所以 -40 ℃ 折成华氏还是 -40,同一行还给 K 233.15、°R 419.67,0 ℃ 折出 32、273.15、491.67。第 4 个单位的界面名是「华氏温标(绝对)」、符号 °R,就是文案里的兰金,界面从不出现那两个字。
结果保留几位:那句「8 位有效」只对 13 个数量级成立
常见问题写着「统一保留 8 位有效数字」,得按代码改口径:dp 取 7 减 log10 的整数部分再夹进 0 到 12。同一串 1.23456789012345 挪数量级实测,恰好 8 个数字的只有 k 从 -5 到 7 这 13 档;k = -6 只剩 7 位,k = 8 给 123,456,789 变 9 位,k = 11 给 123,456,789,012 共 12 位。
图 2|同一串 1.23456789012345 在不同数量级下经格式化函数得到的显示与数字个数,条形按位数等比。
科学计数的门槛也不严:判据是绝对值大于等于 1e12(含等于),1e12 自己就输出 1e+12,而 999999999999.9999 打满 1,000,000,000,000 共 13 位;下限才是小于 1e-6。千分位只加在小数分支,8e11 显示 800,000,000,000 而 8e12 显示 8e+12。11 行或 15 行同屏一次铺开才有意义,省掉的只是「漏看另一行」。
复制、反算,与那张倒置的亩分表
复制与反算拿到的精度不同源:逐条复制是显示串(KB 行 1,048.576、TiB 行 9.536743e-7,还带逗号),反算读的是 data-val 再 toPrecision(12) 写回输入框——1 亩 折平方米显示 666.66667、原始值 666.6666666666666,反算后输入变成 666.666666667,再折回 亩 是 1,真值 1.0000000000005 被抹平。源单位那行没有反算按钮,长度 15 行只有 14 行带。
面积类里 亩 折平方米 666.66667、坪(400 / 121)3.3057851、1 公顷 折亩恰好 15、折坪 3,025 都站得住;出问题的是 分,代码存成 20000 / 3(模板行 57)、折平方米 6,666.6667,于是 1 亩 到 分 显示 0.1、1 分 到 亩 显示 10(原始值 10.000000000000002)。通行定义是 1 亩 = 10 分,这里倒了 100 倍。
Q:为什么 -40 摄氏度读出来还是 -40?
偏移公式在这点自交,两个方向都精确落回 -40,是两种温标唯一的重合点,不是舍入出来的。
Q:为什么 1 MB 有时是 1048576 字节?
那是 MiB 的值:1 MiB 折字节 1,048,576、1 MB 折字节 1,000,000,差 48576。名字里有没有 i 就是分水岭。
Q:大数为什么变成 e 写法,能关掉吗?
绝对值达到 1e12 或小于 1e-6 就切科学计数固定 7 位,代码里没有开关。先乘后除还会把中间量当上限:极端输入 1e308 配 km 时 15 行全成破折号,真值本可表示的 5 行也一起丢了;空输入、abc、1e400 直接落回「请输入需要换算的数值」。