当 .toFixed(2) 小数点后为零时,如何将浮点数格式化为整数?

Posted

技术标签:

【中文标题】当 .toFixed(2) 小数点后为零时,如何将浮点数格式化为整数?【英文标题】:How to format a float as integer when .toFixed(2) gives zeros after the decimal point? 【发布时间】:2018-06-20 12:54:48 【问题描述】:

我想知道实现以下目标的最短和最安全的方法是什么:

假设我有一个值为1.200123 的浮点变量。在我们的可视化中,我想用两位小数显示这个值,所以我现在使用myFloat.toFixed(2);,它给了我1.20

没关系。但是,如果结果输出的小数位只有零怎么办?例如值1.000043 变成1.00

对于上述情况:如何省略小数点和零而只得到1 作为输出,最好不解析和操作来自.toFixed(2) 的字符串?

【问题讨论】:

【参考方案1】:

...最好不解析和操作来自 .toFixed(2) 的字符串?

好吧,你可以用数字来做,虽然我担心在数字逻辑和 toFixed's logic 之间得到完美匹配,因为 toFixed 的定义包括如下短语:

n 为整数,其精确数学值 n ÷ 10f - x 尽可能接近于零。如果有两个这样的 n,则选择较大的 n

所以我可能只是更新字符串,这不是很多工作:

function formatNumber(num) 
    return num.toFixed(2).replace(/\.00$/, "");


function test(num) 
    console.log(num, "=>", formatNumber(num));

test(1.01);
test(1.43);
test(23.7);
test(1.200123);
test(1.000043);
test(1.007);
test(1.0007);

但这里有一个近似的数值方法,它至少与上面测试用例的结果相匹配:

function formatNumber(num) 
    var check = Math.round(num * 100) / 100;
    var rounded = Math.round(check);
    if (rounded == check) 
        return String(rounded);
    
    return num.toFixed(2);


function formatNumberViaToFixed(num) 
    return num.toFixed(2).replace(/\.00$/, "");


function test(num) 
    var formatted = formatNumber(num);
    var viaToFixed = formatNumberViaToFixed(num);
    if (formatted == viaToFixed) 
        console.log(num, "=>", formatted);
     else 
        console.log(num, "=>", formatted, "ERROR: Should be", viaToFixed);
    

test(1.01);
test(1.43);
test(23.7);
test(1.200123);
test(1.000043);
test(1.007);
test(1.0007);
.as-console-wrapper 
  max-height: 100% !important;

【讨论】:

谢谢,T.J.!当有“。”以外的其他字符时,这是“区域设置安全”吗?作为小数点?这就是我在尝试避免使用字符串时一直在考虑的问题。 @Robert - 是的,toFixed 不支持区域设置:tc39.github.io/ecma262/#sec-number.prototype.tofixed 但是,如果是,您可以改用 .replace(/\D00/, ""),因为存在任何非数字成为小数点。 :-) @wiesion - 我做了,虽然肯定不彻底,沿着这些思路:jsfiddle.net/zn0ytkpc 出了什么问题?我完全同意修复或删除。 (虽然盲目 C&P 的人得到了他们应得的。:-))提前谢谢。 OP 要求 1.200123 => 1.201.000043 => 1 - 这是关于通过忽略某个数字后的浮点值来创建一个 int - 你的正则表达式会这样做,但数学方法没有(它为1.000043 提供1.00 确实如此,所以让我们结束这个问题 - 这是一个很好的建设性会议:)【参考方案2】:

你可以使用Number(myFloat.toFixed(2))

虽然这会生成一个类型为 number 而不是 string 的值,但您可以在字符串表达式中使用它(隐式调用其 .toString() 方法),或显式调用 .toString(),以生成您想要的字符串格式想要。

由于Number.toString() 没有特殊格式,将字符串转换为数字然后返回会从.toFixed() 生成的舍入值中删除尾随零。

这种方法的缺点是它将1.10 转换为"1.1" 而不是"1.10",这可能是也可能不是您想要的可视化。

【讨论】:

我还没有想到,有趣的方法!【参考方案3】:

我会在Number 原型中创建这个有条件的toFixed 方法,最终将调用this.toFixed 方法,这样您就可以保持原来的行为并且只调整传递给它的数字数量——即可以使用Math.powMath.trunc 轻松完成。

Object.defineProperty(Number.prototype, 'toConditionalFixed', 
  enumerable: false,
  writable: false,
  configurable: false,
  value: function(digits) 
    let comp = Math.pow(10, digits);
    return this.toFixed(Math.trunc(this * comp) % comp === 0 ? 0 : digits);
  
);


console.log(
  (1.200123).toConditionalFixed(2),
  '|',
  (1.200123).toConditionalFixed(3),
  '|',
  (1.200123).toConditionalFixed(4),
  '|',
  (1.000043).toConditionalFixed(2),
  '|',
  (1.000043).toConditionalFixed(3),
  '|',
  (1.000043).toConditionalFixed(4),
  '|',
  (1.000043).toConditionalFixed(5)
);

编辑

为了完整起见,Number.prototype 中的相同方法适用于 RegExp:

Object.defineProperty(Number.prototype, 'toConditionalFixed', 
  enumerable: false,
  writable: false,
  configurable: false,
  value: function(digits) 
    let re = new RegExp("\\." + "0".repeat(digits)  + "$");
    return this.toFixed(digits).replace(re, "");
  
);

console.log(
  (1.200123).toConditionalFixed(2),
  '|',
  (1.200123).toConditionalFixed(3),
  '|',
  (1.200123).toConditionalFixed(4),
  '|',
  (1.000043).toConditionalFixed(2),
  '|',
  (1.000043).toConditionalFixed(3),
  '|',
  (1.000043).toConditionalFixed(4),
  '|',
  (1.000043).toConditionalFixed(5)
);

【讨论】:

以上是关于当 .toFixed(2) 小数点后为零时,如何将浮点数格式化为整数?的主要内容,如果未能解决你的问题,请参考以下文章

JS处理数据四舍五入,tofixed与round的区别

JS处理数据四舍五入(tofixed与round的区别详解)

JS处理数据四舍五入(tofixed与round的区别详解)

JS怎样做四舍五入

如何强制数字显示 2 位小数?

jquery怎么将4位小数转换成1位