toFixed方法的bug
最近在工作过程中碰到一个隐藏的bug,经调试发现竟然是toFixed函数不可靠的结果引起的。后端同学在处理价格比较的时候,用foFixed进行价格的四舍五入之后,竟然发现比较的结果有问题;
大家都知道,Number类型的变量有个toFixed方法,该方法将Number四舍五入为指定小数位数的数字,以字符串返回。
IE:
1 2 | 0.6 .toFixed(0); // 0 1.6 .toFixed(0); // 2 |
Chrome:
1 2 | 0.6 .toFixed(0); // 1 1.6 .toFixed(0); // 2 |
另外还发现,就算是同在Chrome里,四舍五入也不靠谱:
1 2 | ( 0.035 ).toFixed( 2 ); // 0.04 ( 0.045 ).toFixed( 2 ); // 0.04 |
这次IE倒是靠谱了:
1 2 | ( 0.035 ).toFixed( 2 ); // 0.04 ( 0.045 ).toFixed( 2 ); // 0.05 |
结论
:toFixed()函数靠不住,如果有需要精确控制的情况,还是自己写个方法比较好。比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | function toFixed(number, decimal) { decimal = decimal || 0; var s = String(number); var decimalIndex = s.indexOf( '.' ); if (decimalIndex < 0) { var fraction = '' ; for ( var i = 0; i < decimal; i++) { fraction += '0' ; } return s + '.' + fraction; } var numDigits = s.length - 1 - decimalIndex; if (numDigits <= decimal) { var fraction = '' ; for ( var i = 0; i < decimal - numDigits; i++) { fraction += '0' ; } return s + fraction; } var digits = s.split( '' ); var pos = decimalIndex + decimal; var roundDigit = digits[pos + 1]; if (roundDigit > 4) { //跳过小数点 if (pos == decimalIndex) { --pos; } digits[pos] = Number(digits[pos] || 0) + 1; //循环进位 while (digits[pos] == 10) { digits[pos] = 0; --pos; if (pos == decimalIndex) { --pos; } digits[pos] = Number(digits[pos] || 0) + 1; } } //避免包含末尾的.符号 if (decimal == 0) { decimal--; } return digits.slice(0, decimalIndex + decimal + 1).join( '' ); } var a = 19.02 var b = 209.01 // 结果 console.log(toFixed(a, 2)); //==> 19.02 console.log(toFixed(b, 2)); //==> 209.01 console.log(Number(toFixed(a, 2)) < Number(toFixed(b, 2))); //==> true |
分类:
javascript
标签:
toFixed函数重写
, toFixed函数bug
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!