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

How to format a float as integer when .toFixed(2) gives zeros after the decimal point?

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

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

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

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

...preferrably without parsing and manipulating the string that comes out of .toFixed(2)?

嗯,你可以用数字来做,尽管我担心在数字逻辑和 toFixed's logic 之间得到完美匹配,给定 [=13] 的定义=] 包括像这样的短语:

Let n be an integer for which the exact mathematical value of n ÷ 10f - x is as close to zero as possible. If there are two such n, pick the larger 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;
}

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

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

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

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

我会在 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)
);