263

Have I missed a standard API call that removes trailing insignificant zeros from a number?

var x = 1.234000; // to become 1.234
var y = 1.234001; // stays 1.234001

Number.toFixed() and Number.toPrecision() are not quite what I'm looking for.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Steven
  • 2,789
  • 2
  • 18
  • 12
  • 6
    Um, `1.234000 === 1.234`. – Gumbo Aug 31 '10 at 20:10
  • 5
    Yea, if you do alert(x) it pops up without the trailing zeros – JKirchartz Aug 31 '10 at 20:17
  • 77
    After working with a number of clients, I can testify that even though 1.234000 === 1.234, clients don't want to see those extra zeros if they don't need to. – contactmatt Jan 15 '13 at 16:44
  • 32
    Use `parseFloat(n)` ? – Mr. Alien Apr 07 '16 at 13:13
  • This was the easiest solution that covered all edge cases for me, thank you @Mr.Alien. – James Perih Oct 01 '18 at 21:26
  • the question seems to covering how to remove **significant** trailing zeroes? that's what i'm looking for even though it's not *technically* correct. for non-money related floats, trimming excess zeroes (`75.0%` to `75%`) just "makes sense" to end users. – worc Nov 27 '18 at 00:31
  • my question is: Are leading zeros insignificant? From a mathematical view, 1.2300 means: 4 digits behind the point are exact. and 1.23 means: only 2 digits exact, maybe rounded. Example: Compare 12m and 12.00m – Wiimm Mar 05 '19 at 22:20

24 Answers24

370

I had a similar instance where I wanted to use .toFixed() where necessary, but I didn't want the padding when it wasn't. So I ended up using parseFloat in conjunction with toFixed.

toFixed without padding

parseFloat(n.toFixed(4));

Another option that does almost the same thing
This answer may help your decision

Number(n.toFixed(4));

toFixed will round/pad the number to a specific length, but also convert it to a string. Converting that back to a numeric type will not only make the number safer to use arithmetically, but also automatically drop any trailing 0's. For example:

var n = "1.234000";
    n = parseFloat(n);
 // n is 1.234 and in number form

Because even if you define a number with trailing zeros they're dropped.

var n = 1.23000;
 // n == 1.23;
MrP1us
  • 9
  • 1
  • 6
Gary
  • 13,303
  • 18
  • 49
  • 71
  • 2
    Note that this works only if the relevant number of decimals is equal or greater than the toFixed argument. If the number is for example 1.200000 the result of toFixed(3) will be 1.200 and thus, no all the trailing zeros will be removed. – Leopoldo Sanczyk Nov 16 '15 at 23:37
  • @LeopoldoSanczyk No, that's only true if you're just using toFixed, because it returns a string. Number types automatically lose trailing zeros. That's why I used the two in tandem. – Gary Nov 20 '15 at 02:51
  • @Gary, I withdraw my comment, I have seen `parseFloat(n).toFixed(4);` instead of the your actual answer. I'm sorry. – Leopoldo Sanczyk Nov 20 '15 at 05:58
  • 4
    **Why not `+(n.toFixed(4))`?** – Константин Ван Aug 28 '17 at 03:45
  • The part that explained that toFixed converts it to a string helped me to solve my problem. Thanks for the thorough explanation. – fizch Mar 02 '18 at 17:10
  • 9
    upvoted! only one problem with your answer 0.00000005 gets converted to 5e-8 how can I remove insignificant zeroes without this problem, i am working with small numbers such as 0.000058000 where zeroes at the end need to be removed – PirateApp Dec 12 '18 at 09:32
  • Thanks @Gary, I'm using as Number(n) and it's not displaying trailing zeros! – eldorjon Aug 12 '20 at 12:28
  • parseFloat -> Work better than toString() – Tony Oct 22 '21 at 05:18
183

If you convert it to a string it will not display any trailing zeros, which aren't stored in the variable in the first place since it was created as a Number, not a String.

var n = 1.245000
var noZeroes = n.toString() // "1.245" 
Cristian Sanchez
  • 31,171
  • 11
  • 57
  • 63
  • 6
    I was about to post some code to strip the zeros but Daniel's solution seems to work. It even works for Strings such as "1.2345000". ("1.2345000" * 1).toString(); // becomes 1.2345 – Steven Aug 31 '10 at 21:18
  • 8
    Of course, if your var is already a string you have to convert it to a number first and then back again – derekcohen Jun 27 '11 at 13:03
  • This worked great. I was having the same issue, converted float to string and then parseFloat to get it back in the right format, only without the trailing zeroes. – Matt West Aug 26 '16 at 21:08
  • 16
    This is not complete solution. It doesn't work when you have variable with some floating point representation error, like: `var n = 1.245000000000001` (assuming it is insignificant to be represented to user) – augur Jun 08 '17 at 15:04
  • 11
    May produce unexpected results for numbers like: 1231111111111111111111111111111222222222222222222222222222222222222222222222222222.00. The string representation will be in exponential format: 1.231111111111111e+81 – Stas Makutin Feb 20 '18 at 16:43
  • 3
    Had to revisit this again myself and stumbled on my own answer below. This answer is a good quick-fix, but doesn't solve the second case that the OP gave, where `(1.234001).toString()` still produces `"1.234001"`. The one-liner would be: `(new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 })).format(1.234001)` – dperish Mar 20 '19 at 04:17
  • 1
    How to convert 0.0000000800 to 0.00000008 ? parseFloat, Number and toString functions are returning scientific notation 8e-8 which is not what I want. – Eagle_Eye Jul 01 '19 at 14:11
  • It does not work with `1.000` after some operation, for example. Keeps zeros at end. – Juan Antonio Jan 19 '21 at 08:29
  • 1
    It appears that the wrong answer got accepted, as this answer doesn't do what the question asked for, whereas the answer to "Have I missed a standard API call that removes trailing insignificant zeros from a number?" is "you did, it's just `parseFloat()`". – Mike 'Pomax' Kamermans Apr 04 '21 at 15:04
58

I first used a combination of matti-lyra and gary's answers:

r=(+n).toFixed(4).replace(/\.0+$/,'')

Results:

  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0.0012234: "0.0012"
  • 0.1200234: "0.12"
  • 0.000001231: "0"
  • 0.10001: "0.1000"
  • "asdf": "NaN" (so no runtime error)

The somewhat problematic case is 0.10001. I ended up using this longer version:

    r = (+n).toFixed(4);
    if (r.match(/\./)) {
      r = r.replace(/\.?0+$/, '');
    }
  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0.0012234: "0.0012"
  • 0.1200234: "0.12"
  • 0.000001231: "0"
  • 0.10001: "0.1"
  • "asdf": "NaN" (so no runtime error)

Update: And this is Gary's newer version (see comments):

r=(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')

This gives the same results as above.

w00t
  • 17,944
  • 8
  • 54
  • 62
  • 1
    I've got a pure regex solution that I believe works `toFixed(4).replace(/([0-9]+(\.[1-9]+)?)(\.?0+$)/,"$1")` – Gary Jul 02 '14 at 12:04
  • @Gary closer, now fails for 1.01010 :-) – w00t Jul 03 '14 at 13:12
  • 1
    Gah! Apparently I'm not nearly as good at breaking my own RegExes than others. I will not let this beat me! I ran this one against all of your test cases plus any (valid) one I could think of `([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)` – Gary Jul 03 '14 at 17:09
  • On my phone, so it's hard to test properly, but what about `(\d+\.\d*)0+` for the regex in your replace? I think that covers all cases. The 0+ greedily matches all ending 0s and the \. only allows replacing decimals. When the regex doesn't match, it doesn't do anything. – w00t Jul 05 '14 at 07:40
  • This one only trims a single trailing zero. Also `\.\d` is in the first capture group, so just a decimal and 0's won't ever be replaced. – Gary Jul 05 '14 at 13:25
  • 2
    The regex is to greedy an sometimes removes a "0" from the integer part! :-( Why not just `replace(/[,.][1-9]+(0+)/,'')`? – Sebastian Sebald Sep 26 '14 at 10:37
  • @distractedbysquirrels do you have an example of a failing number? – w00t Sep 26 '14 at 19:14
  • I actually misread something. My returned values (localized Strings, because in Germany we use a comma as decimal seperator...) sometimes do not contain any decimal digits. This is due to the fact, that users can config the numbers of decimal digits :-/ – Sebastian Sebald Sep 29 '14 at 08:19
  • @w00t Sure. 1230009100 - > 123000910 This is number from your example – Jake Blues Dec 19 '16 at 12:56
  • @w00t To reproduce just remove `.toFixed()` – Jake Blues Dec 19 '16 at 13:22
  • @JakeBlues I'm confused, what are you replying to? If you remove the `.toFixed()` then it surely breaks, it is necessary. – w00t Dec 19 '16 at 17:24
  • @w00t You asked distractedbysquirrels example of a failing number so I gave you this example) Actually I think your answer is not quite correct, because from the question `var y = 1.234001; // stays 1.234001` And your answer doesn't cover this condition. – Jake Blues Dec 20 '16 at 10:00
  • 2
    Underrated answer this. – Charlie Nov 08 '18 at 11:03
  • 4
    @w00t Gary's regex fails for 1230009100, use `replace(/\.0*$|(\.\d*[1-9])0+$/, '$1')` or the one from João Costa. see https://regex101.com/r/KmsEFd/1 – geekley Jul 03 '19 at 02:11
  • @geekley I don't see it failing? `f=n=>(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')` `f(1230009100) -> "1230009100"` – w00t Jul 05 '19 at 09:13
  • 1
    @w00t Oh, sorry, I understand now. I was the way I tested when I made mine (see link above). Yours doesn't fail when you use toFixed, because the number is guaranteed to have a dot, but it was failing in my tests because I wanted the regex to work for any number, including integers with no dot. Without toFixed, it eats a zero at the end. My bad. – geekley Jul 06 '19 at 03:31
39

The toFixed method will do the appropriate rounding if necessary. It will also add trailing zeroes, which is not always ideal.

(4.55555).toFixed(2);
//-> "4.56"

(4).toFixed(2);
//-> "4.00"

If you cast the return value to a number, those trailing zeroes will be dropped. This is a simpler approach than doing your own rounding or truncation math.

+(4.55555).toFixed(2);
//-> 4.56

+(4).toFixed(2);
//-> 4
C. J.
  • 893
  • 9
  • 4
  • 1
    tricky, but exactly what i've been looking for: removing *significant* trailing zeros (which of course we made significant through the `toFixed` call). it's a weird UX edge case. – worc Nov 27 '18 at 00:35
34

How about just multiplying by one like this?

var x = 1.234000*1; // becomes 1.234

var y = 1.234001*1; // stays as 1.234001
Koby Douek
  • 16,156
  • 19
  • 74
  • 103
Howard
  • 471
  • 4
  • 3
19

I had the basically the same requirement, and found that there is no built-in mechanism for this functionality.

In addition to trimming the trailing zeros, I also had the need to round off and format the output for the user's current locale (i.e. 123,456.789).

All of my work on this has been included as prettyFloat.js (MIT Licensed) on GitHub: https://github.com/dperish/prettyFloat.js


Usage Examples:

prettyFloat(1.111001, 3) // "1.111"
prettyFloat(1.111001, 4) // "1.111"
prettyFloat(1.1111001, 5) // "1.1111"
prettyFloat(1234.5678, 2) // "1234.57"
prettyFloat(1234.5678, 2, true) // "1,234.57" (en-us)


Updated - August, 2018


All modern browsers now support the ECMAScript Internationalization API, which provides language sensitive string comparison, number formatting, and date and time formatting.

const formatters = {
    default: new Intl.NumberFormat(),
    currency: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    whole: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    oneDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 1, maximumFractionDigits: 1 }),
    twoDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 })
};

formatters.twoDecimal.format(1234.5678);  // result: "1,234.57"
formatters.currency.format(28761232.291); // result: "$28,761,232"

For older browsers, you can use this polyfill: https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en

dperish
  • 1,493
  • 16
  • 27
16

Pure regex answer

n.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1');

I wonder why no one gave one!

João Costa
  • 344
  • 3
  • 11
  • It will not work with numbers (numbers are stated in the original question). I love the solution for a string representation though! – BennyHilarious Dec 01 '18 at 16:18
  • 1
    n.replace(/([\.\,][0-9]*[1-9])0+$|[\.\,]0*$/, '$1') if you want it to work with commas as well – Simon Dec 13 '22 at 10:45
15

You can try this one to minify floating numbers

var n = 0.0000;
n = parseFloat(n.toString()); 

//output n = 0; 
// n = 3.14000; --> n = 3.14;
Amit Panasara
  • 600
  • 8
  • 16
7

If you use toFixed(n) where n > 0, a more simple and stable (no more float operations) solution can be:

(+n).toFixed(2).replace(/(\.0+|0+)$/, '')

// 0 => 0
// 0.1234 => 0.12
// 0.1001 => 0.1

// 1 => 1
// 1.1234 => 1.12
// 1.1001 => 1.1

// 100 => 100
// 100.1234 => 100.12
// 100.1001 => 100.1

PS: if you use toFixed(0), then no replace is needed.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
shawn
  • 4,305
  • 1
  • 17
  • 25
  • 1
    the `.replace(/(\.0+|0+)$/, '')` has bug for the default value of `digits` parameter of the` toFixed()` method which is 0. For example either `(+'10').toFixed().replace(/(\.0+|0+)$/, '')` or `(+'10').toFixed(0).replace(/(\.0+|0+)$/, '')` returns 1 instead of 10. – T.V. Dec 06 '20 at 10:49
  • @T.V. If you use `toFixed(0)`, then no replace is needed at all, no wasting CPU. – shawn Dec 06 '20 at 11:53
  • I did not mean hardcoded zero like this, that's why. – T.V. Dec 06 '20 at 12:24
  • basically you suggest to insert additional `if else` just to check if n is 0 or not, for the case where n is not hardcoded. – T.V. Dec 06 '20 at 12:37
  • And now you are confusing people by using the same 'n' with two different meanings in the same answer :) If you will not accept the edit I will be forced to post it as a separate answer, which is not a best practice for SO, but what can I do. – T.V. Dec 06 '20 at 12:45
  • For the attention of @double deep (the reviewer) who failed to understand why the edit was suggested: Because it fixes bug which was in the original answer. for example, the following code `(+"10").toFixed().replace(/(\.0+|0+)$/, '')` will give a wrong value `1` instead of `10` (and the same is true for `(+"10").toFixed(0).replace(/(\.0+|0+)$/, '')`, The suggested edit corrects this example to be the `(+"10").toFixed(N).replace(/(\.0*|(?<=(\.[0-9]*))0*)$/, '')` which is bug free for any N supported by the `toFixed()` method. Dear "@double deep", suggested edit is simply bug fix, nothing else. – T.V. Dec 06 '20 at 14:12
  • @T.V. You have your choice, others have theirs. Keep things simple. – shawn Dec 06 '20 at 16:42
  • which is simpler `if (digits === 0) { do_stuff(digits); } else { do_other_stuff(digits); }` OR just `do_stuff(digits)`, What I suggested is exactly the second option, which is shorter and simpler, because it do not require you to check if `digits` is zero or not, so it is simpler in addition to be bug free for usage in a general case. Or it should work only for hardcoded `2`? – T.V. Dec 06 '20 at 16:57
6

I needed to solve this problem too when Django was displaying Decimal type values in a text field. E.g. when '1' was the value. It would show '1.00000000'. If '1.23' was the value, it would show '1.23000000' (In the case of a 'decimal_places' setting of 8)

Using parseFloat was not an option for me since it is possible it does not return the exact same value. toFixed was not an option since I did not want to round anything, so I created a function:

function removeTrailingZeros(value) {
    value = value.toString();

    # if not containing a dot, we do not need to do anything
    if (value.indexOf('.') === -1) {
        return value;
    }

    # as long as the last character is a 0 or a dot, remove it
    while((value.slice(-1) === '0' || value.slice(-1) === '.') && value.indexOf('.') !== -1) {
        value = value.substr(0, value.length - 1);
    }
    return value;
}
megasnort
  • 79
  • 1
  • 2
  • This works, however it's quite inefficient, since it results in the creation of multiple strings per execution. Imagine running this on all cells in a table, where a good number were .00000. A better option would be to determine how many trailing zeros there were, then do the slice in one go. Determining what a character is, is largely efficient, splitting strings is less so. – Derek Nigel Bartram Jan 26 '18 at 14:24
  • I did something similar to your suggestion Derek: https://github.com/rek/remove-trailing-zeros/blob/master/remove-trailing-zeros.js – rekarnar Jul 09 '18 at 09:32
  • Perf test is here: https://jsperf.com/remove-trailing-zeros/1, you were right, finding the zeros and removing them is way faster! – rekarnar Jul 10 '18 at 09:38
5

If we have some s string representation of a number, which we can get for example using the .toFixed(digits) method of Number (or by any other means), then for removal of insignificant trailing zeros from the s string we can use:

s.replace(/(\.0*|(?<=(\..*))0*)$/, '')

/**********************************
 * Results for various values of s:
 **********************************
 *
 * "0" => 0
 * "0.000" => 0
 * 
 * "10" => 10
 * "100" => 100
 * 
 * "0.100" => 0.1
 * "0.010" => 0.01
 * 
 * "1.101" => 1.101
 * "1.100" => 1.1
 * "1.100010" => 1.10001
 * 
 * "100.11" => 100.11
 * "100.10" => 100.1
 */

Regular expression used above in the replace() is explained below:

  • In the first place please pay the attention to the | operator inside the regular expression, which stands for "OR", so, the replace() method will remove from s two possible kinds of substring, matched either by the (\.0*)$ part OR by the ((?<=(\..*))0*)$ part.
  • The (\.0*)$ part of regex matches a dot symbol followed by all the zeros and nothing else till to the end of the s. This might be for example 0.0 (.0 is matched & removed), 1.0 (.0 is matched & removed), 0.000 (.000 is matched & removed) or any similar string with all the zeros after the dot, so, all the trailing zeros and the dot itself will be removed if this part of regex will match.
  • The ((?<=(\..*))0*)$ part matches only the trailing zeros (which are located after a dot symbol followed by any number of any symbol before start of the consecutive trailing zeros). This might be for example 0.100 (trailing 00 is matched & removed), 0.010 (last 0 is matched & removed, note that 0.01 part do NOT get matched at all thanks to the "Positive Lookbehind Assertion", i.e. (?<=(\..*)), which is in front of 0* in this part of regex), 1.100010 (last 0 is matched & removed), etc.
  • If neither of the two parts of expression will match, nothing gets removed. This might be for example 100 or 100.11, etc. So, if an input does not have any trailing zeros then it stays unchanged.

Some more examples using .toFixed(digits)(Literal value "1000.1010" is used in the examples below, but we can assume variables instead):

let digits = 0; // Get `digits` from somewhere, for example: user input, some sort of config, etc.

(+"1000.1010").toFixed(digits).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000'

(+"1000.1010").toFixed(digits = 1).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.1'


(+"1000.1010").toFixed(digits = 2).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.1'


(+"1000.1010").toFixed(digits = 3).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'


(+"1000.1010").toFixed(digits = 4).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'


(+"1000.1010").toFixed(digits = 5).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'

(+"1000.1010").toFixed(digits = 10).replace(/(\.0*|(?<=(\..*))0*)$/, '');
// Result: '1000.101'

To play around with the above regular expression used in replace() we can visit: https://regex101.com/r/owj9fz/1

T.V.
  • 467
  • 5
  • 8
  • 1
    Be aware, lookbehind was a more recent addition to JavaScript, and as of the time of this comment, Safari still doesn't support it: https://caniuse.com/js-regexp-lookbehind – Jonathan Tran Jul 27 '22 at 14:57
5

Using parseFloat() did the trick for me. I'm scratching my head here as to why those complicated solutions.

Clemen Canaria
  • 133
  • 2
  • 11
4

None of these solutions worked for me for very small numbers. http://numeraljs.com/ solved this for me.

parseFloat(0.00000001.toFixed(8));
// 1e-8

numeral(0.00000001).format('0[.][00000000]');
// "0.00000001"
Devon
  • 5,786
  • 5
  • 38
  • 46
  • It can't handle more than 6 precision. I would say this library is useless if it's meant for small numbers. Definitely not recommended. – Daniel Kmak Dec 21 '17 at 11:33
3

I needed to remove any trailing zeros but keep at least 2 decimals, including any zeros.
The numbers I'm working with are 6 decimal number strings, generated by .toFixed(6).

Expected Result:

var numstra = 12345.000010 // should return 12345.00001
var numstrb = 12345.100000 // should return 12345.10
var numstrc = 12345.000000 // should return 12345.00
var numstrd = 12345.123000 // should return 12345.123

Solution:

var numstr = 12345.100000

while (numstr[numstr.length-1] === "0") {           
    numstr = numstr.slice(0, -1)
    if (numstr[numstr.length-1] !== "0") {break;}
    if (numstr[numstr.length-3] === ".") {break;}
}

console.log(numstr) // 12345.10

Logic:

Run loop function if string last character is a zero.
Remove the last character and update the string variable.
If updated string last character is not a zero, end loop.
If updated string third to last character is a floating point, end loop.

Kevin H.
  • 31
  • 1
2

If you cannot use Floats for any reason (like money-floats involved) and are already starting from a string representing a correct number, you could find this solution handy. It converts a string representing a number to a string representing number w/out trailing zeroes.

function removeTrailingZeroes( strAmount ) {
    // remove all trailing zeroes in the decimal part
    var strDecSepCd = '.'; // decimal separator
    var iDSPosition = strAmount.indexOf( strDecSepCd ); // decimal separator positions
    if ( iDSPosition !== -1 ) {
        var strDecPart = strAmount.substr( iDSPosition ); // including the decimal separator

        var i = strDecPart.length - 1;
        for ( ; i >= 0 ; i-- ) {
            if ( strDecPart.charAt(i) !== '0') {
                break;
            }
        }

        if ( i=== 0 ) {
            return strAmount.substring(0, iDSPosition);
        } else {
            // return INTPART and DS + DECPART including the rightmost significant number
            return strAmount.substring(0, iDSPosition) + strDecPart.substring(0,i + 1);
        }
    }

    return strAmount;
}
BennyHilarious
  • 373
  • 3
  • 15
2

This is how I do it:

parseFloat(number.toString());

This is a good workaround for the TypeScript bug too. The bug that changes number to string in certain situations.

QuanDar
  • 1,255
  • 2
  • 12
  • 20
1

I wrote this regular expression to remove insignificant: zeros, decimals, and spaces from the beginning and end of strings containing numbers:

const rxInsignificant = /^[\s0]+|(?<=\..*)[\s0.]+$|\.0+$|\.$/gm;

let ary = [
"001.230",
"2.",
"3.00",
"1000",
" 0000000000000010000.10000000000000000000000  "];

ary.forEach((str)=>
{
  console.log(`"${str}" becomes "${str.replace(rxInsignificant,'')}"`);
});

Unfortunately, Safari still doesn't support the 2018 specification that gave us look-behinds in regular expressions. There has been an open bug report for this issue since 07-28-2017.

The good news is that look-behinds do work in Firefox and in all Chromium derivatives. Hopefully, Safari will receive more requests for this compliance and implement this standard soon.

In the meantime, I've written this function to accomplish the same task without a look-behind:

function createRemoveInsignificantFunction()
{
  const rxLeadingZeros = /^[\s0]+/;
  const rxEndingZeros = /[\s0]+$/;
  function removeInsignificant(str)
  {
    str = str.replace(rxLeadingZeros,'');
    let ary = str.split('.');
    if (ary.length > 1)
    {
      ary[1] = ary[1].replace(rxEndingZeros,'');
      if (ary[1].length === 0)
      {
        return ary[0];
      }
      else
      {
        return ary[0] + '.' + ary[1];
      }         
    }
    return str;
  }
  return removeInsignificant;
}
let removeInsignificant = createRemoveInsignificantFunction();
let ary = [
"001.230",
"2.",
"3.00",
"1000",
" 0000000000000010000.10000000000000000000000  "];
ary.forEach((str)=>
{
  console.log(`"${str}" becomes "${removeInsignificant(str)}"`);
});

When I have more time, I'd like to figure out how to accomplish this with one regular expression that does not have a look-behind in it. You're welcome to beat me to it in the comments below.

Lonnie Best
  • 9,936
  • 10
  • 57
  • 97
1

If you'd also like to deal with numeric errors, you could use Intl.NumberFormat or Number.toLocaleString()

new Intl.NumberFormat().format(0.0100) // "0.01"
new Intl.NumberFormat().format(0.010000000000001) // "0.01"
new Intl.NumberFormat().format(0.009999999999999) // "0.01"
console.log((0.0100).toLocaleString()) // "0.01"
console.log((0.010000000000001).toLocaleString()) // "0.01"
console.log((0.009999999999999).toLocaleString()) // "0.01"
Michał Miler
  • 152
  • 1
  • 9
1

So you want

var x = 1.234000; // to become 1.234
var y = 1.234001; // stays 1.234001

No strings attached, just try Number().

var x  = 1.234000, // to become 1.234
    y  = 1.234001, // stays 1.234001
    x_ = Number(x),
    y_ = Number(y);

console.log(x_,y_);
Redu
  • 25,060
  • 6
  • 56
  • 76
  • fails on x=0.000001 – Matthew Cornelisse Feb 23 '22 at 18:40
  • @MatthewCornelisse Could you please elaborate. What result you expected and what you got instead. – Redu Feb 23 '22 at 18:49
  • with small values the value is returned in scientific notation which I do not believe is desired. I did add an answer with a function I have used in similar place – Matthew Cornelisse Feb 23 '22 at 20:37
  • Well not for `0.000001` but for `Number(0.0000001)` you get `1e-7` which is perfectly normal JS jargon which is also out of the topic of this question. However if you still really want to convert it into decimal string then just capture the last digit in the scientific notation (which is 7 in this case) and do like `1e-7.toFixed(7)`. – Redu Feb 23 '22 at 20:54
  • I do understand scientific notation and that method won't work 0.0000000001 last digit would be a 0. Just pointing out your answer does not provide the requested output for any small value. – Matthew Cornelisse Feb 23 '22 at 21:10
0

After reading all of the answers - and comments - I ended up with this:

function isFloat(n) {
    let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n)) : n;
    return number;
}

I know using eval can be harmful somehow but this helped me a lot.

So:

isFloat(1.234000);     // = 1.234;
isFloat(1.234001);     // = 1.234001
isFloat(1.2340010000); // = 1.234001

If you want to limit the decimal places, use toFixed() as others pointed out.

let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n).toFixed(3)) : n;

That's it.

ed1nh0
  • 1,532
  • 13
  • 17
0

My solution is as follow:

export const floatToStr = (f, ndigit = 2) => {
    const str = f.toFixed(ndigit)
    return ndigit
        ? str
            .replace(/0*$/g, '')
            .replace(/\.$/, '')
        : str
}
Sang
  • 4,049
  • 3
  • 37
  • 47
0

I think the following function may be close to what you want. I wrote it for an application of mine. It will always output in standard notation with no trailing zeros. A few things you may not want but can edit out if you like. It will always return at least one decimal(e.x. 5=>"5.0"). It also is limited to 10 decimals. Use it as a guide.

const toDecimalStr(value)=>{
  let str=value.toFixed(10).replace(/([0]+)$/,"");
  try {
    if (str.endsWith(".")) str+='0';
  } catch (e) {
    str+='0';
  }
  return str;
}

the try catch is because not everything supports endsWith and I was being lazy.

0

Simple, readable and also handles long numbers, Based on the solution by megasnort

function removeTrailingZeros(num: number) : number {
  let value = num.toString();

  const indexOfDot = value.indexOf('.');
  if (indexOfDot === -1) {
      return num;
  }

  let i = value.length - 1;
  while ((value[i] === "0" || value[i] === ".") && i > indexOfDot - 1) {
    value = value.substring(0, i);
    i--;
  }
  return +value;
} 
Tal Segal
  • 2,735
  • 3
  • 21
  • 17
-1

Here's a possible solution:

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001

eval(x) --> 1.234
eval(y) --> 1.234001
sir_thursday
  • 5,270
  • 12
  • 64
  • 118
Moon
  • 43
  • 1