Mohsen Alyafei
Mohsen Alyafei

Reputation: 5557

Regex for Numbers Zeros TrimAll (Large Numbers)

I am looking for one (1) regex to remove all leading and trailing zeros from large decimal numbers (whole and fractional numbers) that may not work with parseFloat().

All posts on Stackoverflow searched and found to address different situations (leading zeros and trailing zeros, etc. for either a whole number only or a fractional number only) but not when a number could be entered both as an integer or a fraction.

Many of the regex I found on SO to trim trailing zeros assume the number is always a fraction and remove trailing zeros in whole numbers.

I have the following one-liner but still needs to have added to it the part that removes the trailing zeros from fractional numbers.

The tests below are self-explanatory.

I am looking for a single regex solution.

Please note that number Input is in String Form.

Thanks

function numberTrimAll(numString) {
// remove leading and trailing zeros from deciaml numbers
// Both whole and fractional numbers
//
// Need to include the following (or one replacement) regex the part that
// trims the trailing zeros in a fractional nummber.
//
  return numString.replace(/([\.]0+$)|^0+(?=\d)/g,"");
}


//--------- following passed ----------------------
test( 1,"00100"       ,"100"     )
test( 2,"00100.0"     ,"100"     )
test( 3,"0100.00"     ,"100"     )
test( 4,"00100100.00" ,"100100"  )
test( 5,"00100101.00" ,"100101"  )
test( 6,"0000.101"    ,"0.101"   )
test( 7,"0000.1001"   ,"0.1001"  )
test( 8,"120000"      ,"120000"  )
test( 9,"00120000"    ,"120000"  )
test(10,"00000001288765433.123456789123567" ,"1288765433.123456789123567")
test(11,"0000001.123456789123567" ,"1.123456789123567")

// ------------ following failed -------------
test(12,"0000.10"     ,"0.1"     )
test(13,"0000.100"    ,"0.1"     )
test(14,"0000.123100" ,"0.1231"  )
test(16,"0500.123100" ,"500.1231")
test(14,"0500.002100" ,"500.0021")


//============ test function ==================
function test(test,input,should){
var  out=numberTrimAll(input),r=out===should?true:false;
if (!r) console.log("Test "+test+" Failed: "+out+" should be ==> "+should);
else console.log("Passed");}

Upvotes: 0

Views: 98

Answers (3)

Mohsen Alyafei
Mohsen Alyafei

Reputation: 5557

Update January 2021 with Alternative Solution

The original function assumes the use of a dot "." (the decimal point) as the decimal separator in the Regex. This, therefore, limits the use of the function.

This new function uses the locale decimal separator and uses an alternative method by splitting the large float number into its whole and decimal parts, then processes each separately and joins the parts again. Therefore, allowing for large number strings as was with the original function.

Testing is also provided for additional cases.

function numberTrimAllZeros(n) {
let Sep = 0.1.toLocaleString().substr(1,1); // Sep = Locale Decimal separator
n = (n+"").split(Sep);                      // Split Number using Sep into Array
if (n.length !==2) n[1]="";                 // No decimal part? Avoid "undefined"
let w =n[0].replace(/^0+/, ''),             // w = whole part => remove leading zeros
    d =n[1].replace(/0+$/, '');             // d = decimal part => remove trailing zeros
return (w ? w : "0")                        // If no whole part then insert 0
       + (d ? Sep : "")                     // Add Decimal Separator only if there is a decimal part
       + d;                                 // Add the decimal part (if any)
}
//=====================================
// Test
//=====================================
test( 1,"00100"       ,"100"     );
test( 2,"00100.0"     ,"100"     );
test( 3,"0100.00"     ,"100"     );
test( 4,"00100100.00" ,"100100"  );
test( 5,"00100101.00" ,"100101"  );
test( 6,"0000.101"    ,"0.101"   );
test( 7,"0000.1001"   ,"0.1001"  );
test( 8,"120000"      ,"120000"  );
test( 9,"00120000"    ,"120000"  );
test(10,"00000001288765433.123456789123567" ,"1288765433.123456789123567");
test(11,"0000001.123456789123567" ,"1.123456789123567");
test(12,"0000.10"     ,"0.1"     );
test(13,"0000.100"    ,"0.1"     );
test(14,"0000.123100" ,"0.1231"  );
test(15,"0500.123100" ,"500.1231");
test(16,"0500.002100" ,"500.0021");
test(17,".6780000"    ,"0.678"   );
test(18,".0"          ,"0"       );
test(19,"0.0"         ,"0"       );
test(20,"0."          ,"0"       );
test(21,"00100.012345678912356700000" ,"100.0123456789123567");
test(22,"00100.012345678912356789167624559998769900000" ,"100.0123456789123567891676245599987699");
test(23, 100          ,"100"     );
test(24, 100.10101    ,"100.10101");
test(25, 0.10101      ,"0.10101" );
test(26, 0.0          ,"0"       );
test(27, ""           ,"0"       );
test(28, "."          ,"0"       );

//============ test function ==================
function test(test,input,should){
var  out=numberTrimAllZeros(input),r=out===should?true:false;
if (!r) console.log("Test "+test+" Failed: "+out+" should be ==> "+should);
else console.log("Passed");}

Upvotes: 0

user120242
user120242

Reputation: 15268

I'd honestly use BigNumber or big.js and call it a day.
But here's a regex using positive lookbehind as another match option.
Note: lookbehind not supported in Safari and some other browsers

function numberTrimAll(numString) {
// remove leading and trailing zeros from deciaml numbers
// Both whole and fractional numbers
//
// Need to include the following (or one replacement) regex the part that
// trims the trailing zeros in a fractional nummber.
//
  return numString.replace(/([\.]0+$)|((?<=[\.][0-9]*?)0+$)|^0+(?=\d)/g,"");
}


//--------- following passed ----------------------
test( 1,"00100"       ,"100"     )
test( 2,"00100.0"     ,"100"     )
test( 3,"0100.00"     ,"100"     )
test( 4,"00100100.00" ,"100100"  )
test( 5,"00100101.00" ,"100101"  )
test( 6,"0000.101"    ,"0.101"   )
test( 7,"0000.1001"   ,"0.1001"  )
test( 8,"120000"      ,"120000"  )
test( 9,"00120000"    ,"120000"  )
test(10,"00000001288765433.123456789123567" ,"1288765433.123456789123567")
test(11,"0000001.123456789123567" ,"1.123456789123567")

// ------------ following failed -------------
test(12,"0000.10"     ,"0.1"     )
test(13,"0000.100"    ,"0.1"     )
test(14,"0000.123100" ,"0.1231"  )
test(16,"0500.123100" ,"500.1231")
test(14,"0500.002100" ,"500.0021")


//============ test function ==================
function test(test,input,should){
var  out=numberTrimAll(input),r=out===should?true:false;
if (!r) console.log("Test "+test+" Failed: "+out+" should be ==> "+should);
else console.log("Passed");}

Upvotes: 1

Nick
Nick

Reputation: 147176

Here's an alternate approach which rather than attempting to strip leading and trailing zeros, captures the non-zero parts in the middle instead.

function numberTrimAll(numString) {
// remove leading and trailing zeros from deciaml numbers
// Both whole and fractional numbers
//
// Need to include the following (or one replacement) regex the part that
// trims the trailing zeros in a fractional nummber.
//
  return numString.replace(/^0*(\d+|\d+\.\d+?)\.?0*$/,"$1");
}


//--------- following passed ----------------------
test( 1,"00100"       ,"100"     )
test( 2,"00100.0"     ,"100"     )
test( 3,"0100.00"     ,"100"     )
test( 4,"00100100.00" ,"100100"  )
test( 5,"00100101.00" ,"100101"  )
test( 6,"0000.101"    ,"0.101"   )
test( 7,"0000.1001"   ,"0.1001"  )
test( 8,"120000"      ,"120000"  )
test( 9,"00120000"    ,"120000"  )
test(10,"00000001288765433.123456789123567" ,"1288765433.123456789123567")
test(11,"0000001.123456789123567" ,"1.123456789123567")

// ------------ following failed -------------
test(12,"0000.10"     ,"0.1"     )
test(13,"0000.100"    ,"0.1"     )
test(14,"0000.123100" ,"0.1231"  )
test(16,"0500.123100" ,"500.1231")
test(14,"0500.002100" ,"500.0021")


//============ test function ==================
function test(test,input,should){
var  out=numberTrimAll(input),r=out===should?true:false;
if (!r) console.log("Test "+test+" Failed: "+out+" should be ==> "+should);
else console.log("Passed");}

Upvotes: 1

Related Questions