strnum.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;
  2. const numRegex = /^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/;
  3. // const octRegex = /^0x[a-z0-9]+/;
  4. // const binRegex = /0x[a-z0-9]+/;
  5. const consider = {
  6. hex : true,
  7. // oct: false,
  8. leadingZeros: true,
  9. decimalPoint: "\.",
  10. eNotation: true,
  11. //skipLike: /regex/
  12. };
  13. function toNumber(str, options = {}){
  14. options = Object.assign({}, consider, options );
  15. if(!str || typeof str !== "string" ) return str;
  16. let trimmedStr = str.trim();
  17. if(options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str;
  18. else if(str==="0") return 0;
  19. else if (options.hex && hexRegex.test(trimmedStr)) {
  20. return parse_int(trimmedStr, 16);
  21. // }else if (options.oct && octRegex.test(str)) {
  22. // return Number.parseInt(val, 8);
  23. }else if (trimmedStr.search(/[eE]/)!== -1) { //eNotation
  24. const notation = trimmedStr.match(/^([-\+])?(0*)([0-9]*(\.[0-9]*)?[eE][-\+]?[0-9]+)$/);
  25. // +00.123 => [ , '+', '00', '.123', ..
  26. if(notation){
  27. // console.log(notation)
  28. if(options.leadingZeros){ //accept with leading zeros
  29. trimmedStr = (notation[1] || "") + notation[3];
  30. }else{
  31. if(notation[2] === "0" && notation[3][0]=== "."){ //valid number
  32. }else{
  33. return str;
  34. }
  35. }
  36. return options.eNotation ? Number(trimmedStr) : str;
  37. }else{
  38. return str;
  39. }
  40. // }else if (options.parseBin && binRegex.test(str)) {
  41. // return Number.parseInt(val, 2);
  42. }else{
  43. //separate negative sign, leading zeros, and rest number
  44. const match = numRegex.exec(trimmedStr);
  45. // +00.123 => [ , '+', '00', '.123', ..
  46. if(match){
  47. const sign = match[1];
  48. const leadingZeros = match[2];
  49. let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros
  50. //trim ending zeros for floating number
  51. if(!options.leadingZeros && leadingZeros.length > 0 && sign && trimmedStr[2] !== ".") return str; //-0123
  52. else if(!options.leadingZeros && leadingZeros.length > 0 && !sign && trimmedStr[1] !== ".") return str; //0123
  53. else if(options.leadingZeros && leadingZeros===str) return 0; //00
  54. else{//no leading zeros or leading zeros are allowed
  55. const num = Number(trimmedStr);
  56. const numStr = "" + num;
  57. if(numStr.search(/[eE]/) !== -1){ //given number is long and parsed to eNotation
  58. if(options.eNotation) return num;
  59. else return str;
  60. }else if(trimmedStr.indexOf(".") !== -1){ //floating number
  61. if(numStr === "0" && (numTrimmedByZeros === "") ) return num; //0.0
  62. else if(numStr === numTrimmedByZeros) return num; //0.456. 0.79000
  63. else if( sign && numStr === "-"+numTrimmedByZeros) return num;
  64. else return str;
  65. }
  66. if(leadingZeros){
  67. return (numTrimmedByZeros === numStr) || (sign+numTrimmedByZeros === numStr) ? num : str
  68. }else {
  69. return (trimmedStr === numStr) || (trimmedStr === sign+numStr) ? num : str
  70. }
  71. }
  72. }else{ //non-numeric string
  73. return str;
  74. }
  75. }
  76. }
  77. /**
  78. *
  79. * @param {string} numStr without leading zeros
  80. * @returns
  81. */
  82. function trimZeros(numStr){
  83. if(numStr && numStr.indexOf(".") !== -1){//float
  84. numStr = numStr.replace(/0+$/, ""); //remove ending zeros
  85. if(numStr === ".") numStr = "0";
  86. else if(numStr[0] === ".") numStr = "0"+numStr;
  87. else if(numStr[numStr.length-1] === ".") numStr = numStr.substr(0,numStr.length-1);
  88. return numStr;
  89. }
  90. return numStr;
  91. }
  92. function parse_int(numStr, base){
  93. //polyfill
  94. if(parseInt) return parseInt(numStr, base);
  95. else if(Number.parseInt) return Number.parseInt(numStr, base);
  96. else if(window && window.parseInt) return window.parseInt(numStr, base);
  97. else throw new Error("parseInt, Number.parseInt, window.parseInt are not supported")
  98. }
  99. module.exports = toNumber;