前天改一个表单校验,用户填数量填了个负一,后端直接把库存算成负数发出去,仓管一脸懵。回头一查,校验规则里只写了大于零,没把零本身挡住,正实数这个边界又把人坑了。
先把定义理清楚。实数就是数轴上所有的点,包括整数、小数、分数,也包括负数和零。正实数就是大于零的那部分,注意零不算正数,负号更不算,所以取值区间是从零往右开,零点本身取不到。
正和「非负」已经是两码事
很多人混着用,正实数表示大于零,非负实数表示大于等于零,差的就是那个零。做年龄、价格、件数这种字段,通常要的是正实数,零得挡掉。做差额、偏移量这类,零是合法值,就得用非负。写校验前先想清楚这个字段到底允不允许零。
正则和代码里怎么写才不容易漏
HTML 输入框可以直接用 type 等于 number 配 min 属性,但 min 是包含式的,设成零其实放过了零,要挡零得设成 0.0001 那种小正数,或者干脆在 JS 里判。正则想匹配正实数,常见写法是排除零和负号,别用只写数字的那种,它会把零和负数都放进来。
Java 里可以用 BigDecimal 的 compareTo 和零比较,返回正数才是正的。Python 里写大于零的条件时,记得浮点数比大小有时候会抖,做金额用 Decimal 更稳。
- 价格和数量:要求严格大于零,零就是脏数据
- 坐标和偏移:零合法,用非负判断
- 科学计算:注意浮点误差,边界值别用等号硬比
还有个细节容易被忽略,负零在浮点里存在,虽然它等于零,但打印出来带个负号,看着别扭,输出前顺手归一化一下。
再补个实际会碰到的边界,科学计数法。用户在输入框敲了 1e3,看着像带字母,其实解析出来是一千,是正实数。有些校验只认纯数字字符串,会把它误判成非法,这时候得先按数值解析再判断正负,而不是拿字符串硬套规则。
还有单位换算带来的零问题。毫米换成米,一点五毫米出来是零点零零一五,正常处理;但换算后又四舍五入到两位,正好成了零,本来合法的正数被舍成了零,日志里就冒出个不该出现的零值。这类地方要么多留几位小数,要么在入库前单独拦一道。
说到底就一句,写规则先把零归哪边定死,再写大于还是大于等于,边界想明白,后面省一堆对账。