You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中能否使用toLocaleString()截断数字且不触发四舍五入?

问题根因

返回值异常和两个因素直接相关:

  • JavaScript的Number类型是64位双精度浮点数,十进制的9.95无法被二进制精确存储,实际内存中的值约为9.950000000000001,本身略大于字面量标注的9.95。
  • 核心原因是当前使用的运行时没有实现toLocaleString底层依赖的Intl.NumberFormat的roundingMode参数,传入的trunc配置被静默忽略,走了默认的四舍五入逻辑,略大于9.95的存储值被进位后就输出了10.0。

你当前用的(9.95).toString().substring(0,3)写法鲁棒性极差,遇到多位数整数、负数、小于1的小数都会返回错误结果,比如10.95会被截成"10",-9.95会被截成"-9.",不建议使用。

可靠实现方案

方案1:新版运行时标准写法

如果你使用的Deno版本在1.25及以上(对应Chrome 106+、Node 19+),roundingMode参数可以正常生效,直接使用标准配置即可:

const formatResult = (9.95).toLocaleString('en-US', {
  minimumFractionDigits: 1,
  maximumFractionDigits: 1,
  roundingMode: "trunc"
});
// 正常输出 "9.9"

方案2:全环境兼容写法

如果需要兼容不支持roundingMode的旧运行时,先用数学方法完成截断,再做本地化格式化,完全规避API的舍入逻辑问题:

/**
 * 按指定位数截断小数,不做四舍五入
 * @param {number} num 待处理数值
 * @param {number} places 保留小数位数
 * @returns {number} 截断后的数值
 */
function truncDecimal(num, places) {
  const scale = 10 ** places;
  return Math.trunc(num * scale) / scale;
}

const truncatedVal = truncDecimal(9.95, 1);
const formatResult = truncatedVal.toLocaleString('en-US', {
  minimumFractionDigits: 1,
  maximumFractionDigits: 1
});
// 所有环境均输出 "9.9"
补充说明

如果是处理金额这类对精度要求极高的场景,不要直接用原生Number做运算,建议先将数值转成最小货币单位的整数(比如人民币转成分)计算后再转译,避免浮点数精度误差导致的资损问题。

内容的提问来源于stack exchange,提问作者Brass P.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 18:22:17