简体   繁体   中英

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

I wonder what would be the shortest and safest way to achieve the following:

Suppose I have a float var with the value 1.200123 . In our visualization, I want to show this value with two decimal places, so I use myFloat.toFixed(2); at the moment, which gives me 1.20 .

That's fine. But what if the resulting output only has zeros at the decimal places? For example the value 1.000043 which becomes 1.00 .

For the case above: how can I omit the decimal point and the zeros and just get 1 as output, preferrably without parsing and manipulating the string that comes out of .toFixed(2) ?

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

Well, you could do it numerically, though I'd worry about getting a perfect match between numeric logic and toFixed 's logic , given the definition of toFixed includes phrases like:

Let n be an integer for which the exact mathematical value of n ÷ 10 f - x is as close to zero as possible. If there are two such n , pick the larger n .

So I'd probably just update the string, it's not a lot of work:

 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); 

But here's an approximate numeric approach, which at least matches the results for the test cases above:

 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; } 

I would create this conditional toFixed method within the Number prototype, which in the end will call the this.toFixed method so that you will keep that original behavior and only adjust the amount of digits passed to it - that can be easily done with Math.pow and Math.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) ); 

EDIT

For the sake of completeness, the same method within Number.prototype which works with 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) ); 

You could use Number(myFloat.toFixed(2)) .

While this produces a value with type number rather than string , you can use it in a string expression (implicitly calling its .toString() method), or call .toString() explicitly, to produce the string format you want.

As Number.toString() does no special formatting, converting the string to a number and then back removes trailing zeroes from rounded value produced by .toFixed() .

The downside of this method would be that it converts 1.10 to "1.1" rather than "1.10" , which may or may not be what you want for your visualisation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM