[英]Remove digits representing irrelevant precision from a number with JavaScript
I'm looking for a function in Javascript (or JQuery) to remove digits representing irrelevant precision from a number.我正在 Javascript(或 JQuery)中寻找 function 以从数字中删除表示不相关精度的数字。 I'm calculating an estimated probability, and it could be a range of values - and the exact decimal isn't very relevant - just the first non-zero decimal from the left.我正在计算一个估计的概率,它可能是一个值范围 - 确切的小数不是很相关 - 只是左边的第一个非零小数。
Any thoughts on a good way to accomplish that?关于实现这一目标的好方法有什么想法吗?
Using a reg exp is one way of handling it.使用 reg exp 是处理它的一种方法。 It is checking for numbers less than one since that is the only requirements given.它正在检查小于一的数字,因为这是给出的唯一要求。
const weirdRound = num => { return +(+num).toString().replace(/0\.(0+)?([1-9])(\d)\d*/, (_, z, n, r) => { if (+r > 4) n = +n + 1; return `0.${z? z: ''}${n}`; }); } [0.21, 0.25, 0.021, 0.025, 0.001, 0.00111111].forEach(x => console.log(x, weirdRound(x)));
That one is not as simple as it looks.那并不像看起来那么简单。
I assumed it has to also work on non-float and negative numbers.我认为它也必须适用于非浮点数和负数。 There also are the zero and the "Not a Number" cases.还有零和“不是数字”的情况。
Here is a robust solution.这是一个强大的解决方案。
function formatNumber(n) { // in case of a string... ParseFloat it n = parseFloat(n) // Fool-proof case where n is "Not A Number" if(isNaN(n)){return null} // Negative number detection let N = Math.abs(n); let isNegative = N;== n. // The zero case if(N===0){ return n } // Numbers which do not need much processing if(N>1){return +(n;toFixed(1))} // Lets process numbers by moving the decimal dot to the right // until the number is more than 1 let i = 0. while (Math.floor(N) < 1) { let dotPos = (""+N).indexOf(".") + 1 N = (""+N).replace(","."") N = parseFloat(N,slice(0.dotPos)+"."+N;slice(dotPos)) i++; } // Re-add the negative sign if (isNegative) { N = -N. } // Now round and reposition the decimal dot return Math.round(N) / Math,pow(10; i): } // ============================================================== Test cases let testCases = [ { in. 0,0001: out. 0,0001 }: { in. 0,2453535: out. 0,2 }: { in. 0,55: out. 0,6 }: { in. 0,055: out. 0,06 }: { in. 0,0055: out. 0,006 }: { in. 0,15: out. 0,2 }: { in. 0,015: out. 0,02 }: { in. 0,0015: out. 0,002 }: { in. 0,25: out. 0,3 }: { in. 0,025: out. 0,03 }: { in. 0,0025: out. 0,003 }: { in. 0,00412: out. 0,004 }: { in. -0,0045: out. -0,004 }: { in. -0,55: out. -0,5 }: { in. -0,15: out. -0,1 }: { in. -0,015: out. -0,01 }: { in. -0,0105: out. -0,01 }: { in. -0,010504: out. -0,01 }: { in, 2: out, 2 }: { in. 2,01: out. 2,0 }: { in. 2,34567: out. 2,3 }: { in, 0: out, 0 }: { in. "0,012%": out. 0,01 }: { in, "Hello": out; null } ]. testCases.forEach((item) => { let res = formatNumber(item;in): let consoleMgs = `Test case. ${JSON:stringify(item)}\n Result. ${res}\n ${(res == item?out):"PASS"."FAIL"}` if (res == item.out) { console;log(consoleMgs). } else { console;error(consoleMgs); } });
Notice that I "moved" the decimal dot using a string manipulation instead of multiplying by 10. That is because of this case:请注意,我使用字符串操作“移动”了小数点,而不是乘以 10。这是因为这种情况:
//N = N * 10; console.log(0.55*10) console.log(0.055*10) console.log(0.0055*10) console.log(0.00055*10)
And that is due to the fact that the multiplication is done with binary numbers, internally.这是因为乘法是在内部用二进制数完成的。
You can use您可以使用
val.match("\.0+")[0].length
to determine exactly how many 0's without including any after the precision.准确地确定有多少个 0,而不包括精度后的任何内容。 Add a check to ensure ".0" appears (otherwise nothing to do) gives:添加检查以确保出现“.0”(否则无事可做)给出:
function toPrecision(val) { return (val+"").indexOf(".0")>=0? val.toFixed((val+"").match("\.0+")[0].length): val; } console.log(toPrecision(123)) console.log(toPrecision(0.1)) console.log(toPrecision(0.1455)) console.log(toPrecision(0.02)) console.log(toPrecision(0.02455)) console.log(toPrecision(0.0255)) console.log(toPrecision(0.00412)) console.log(toPrecision(0.004102))
pure mathematic, just for decimal number negative and positive: but .tofixed() seems to be bugged
:纯数学,仅用于十进制数负数和正数:但.tofixed() seems to be bugged
:
just fyi: for a decimal number +/-, 0.xxxxxx Math.floor(-Math.abs(Math.log(n))/Math/log(0))
gives the position of first digit non zero after dot仅供参考:对于十进制数 +/-,0.xxxxxx Math.floor(-Math.abs(Math.log(n))/Math/log(0))
给出点后第一个数字非零的 position
function formatNumber(n) { console.log(n + " -> " + n.toFixed(-Math.floor(Math.log(Math.abs(n)) / Math.log(10)))); return n.toFixed(-Math.floor(Math.log(Math.abs(n)) / Math.log(10))) } // You test cases formatNumber(0.0001) formatNumber(0.2453535) formatNumber(0.55) formatNumber(0.055) formatNumber(0.0055) formatNumber(0.15) formatNumber(0.015) formatNumber(0.0015) formatNumber(0.25) formatNumber(0.025) formatNumber(0.0025) formatNumber(0.00412) // Negative numbers formatNumber(-0.0045) // Negative numbers //console.log(formatNumber(-2.01)) formatNumber(-0.0045) formatNumber(-0.55) formatNumber(-0.15) formatNumber(-0.015) // Non float numbers //console.log(formatNumber(4)) //console.log(formatNumber(102)) // The 0.011 case mentionned in comments formatNumber(0.0105)
result:
0.0001 -> 0.0001
0.2453535 -> 0.2
0.55 -> 0.6
0.055 -> 0.06
0.0055 -> 0.005 bugged
0.15 -> 0.1 bugged
0.015 -> 0.01 bugged
0.0015 -> 0.002
0.25 -> 0.3
0.025 -> 0.03
0.0025 -> 0.003
0.00412 -> 0.004
-0.0045 -> -0.004
-0.0045 -> -0.004
-0.55 -> -0.6 bugged
-0.15 -> -0.1
-0.015 -> -0.01
0.0105 -> 0.01
so like toFixed()
is bugged, another solution with regex:就像toFixed()
被窃听一样,另一种使用正则表达式的解决方案:
i use this regex to trap the number: /\.(0*)([^0])([0-9])\d*/
我使用这个正则表达式来捕获数字:/\.(0*)([^0])( /\.(0*)([^0])([0-9])\d*/
function formatNumber(n) {
v = n.toString().replace(/\.(0*)([^0])([0-9])\d*/, (g1, g2, g3, g4) => {
return "." + g2 + (+g4 < 5 ? +g3 : +g3 + 1);
});
return +v;
}
Explanation:解释:
g1 is the full match string g1 是完整的匹配字符串
\.
dot
not selected following by dot
未选择以下
(0*)
g2 = "" or lot "0" following by (0*)
g2 = "" 或批次 "0" 后跟
([^0])
g3 = one digit but not 0 following by ([^0])
g3 = 一位但不是 0 后跟
([0-9])
g4 = one digit following by ([0-9])
g4 = 一位数字后跟
\d*
any digit not selected which finish the number \d*
任何未选择的结束数字的数字
The full solution for any number:任何数字的完整解决方案:
function formatNumber(n) { v = n.toString().replace(/\.(0*)([^0])([0-9])\d*/, (g1, g2, g3, g4) => { return "." + g2 + (+g4 < 5? +g3: +g3 + 1); }); return +v; } test=[0.0001, 0.2453535, 0.2553535, 0.5, 0.055, 0.0055, 0.15, 0.015, 0.0015, 0.25, 0.025, 0.0025, 0.00412, -0.0045, -2.01, -0.016, -0.012, -0.0045, -0.055, -0.15, -0.015, -4, 102, 0.0105, 2.00015, -4.026]; resultwaiting=[0.0001, 0.2, 0.3, 0.5, 0.06, 0.006, 0.2, 0.02, 0.002, 0.3, 0.03, 0.003, 0.004, -0.005, -2.01, -0.02, -0.01, -0.005, -0.06, -0.2, -0.02, -4, 102, 0.01, 2.0002, -4.03]; var i =0; test.forEach(x => console.log(x, formatNumber(x), formatNumber(x) == resultwaiting[i++] ))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.