【问题标题】:JavaScript: Trim .toPrecision() trailing zerosJavaScript:修剪 .toPrecision() 尾随零
【发布时间】:2013-05-09 21:27:16
【问题描述】:

我正在使用 JavaScript 创建一个在线计算器。

我有这个计算:

eval(expression).toPrecision(10);

这几乎在所有情况下都会产生正确的输出。例如

eval('456456+45646486*45646884').toPrecision(10)
// Output: "2.083619852e+15"

eval('1/0').toPrecision(10)
// Output: "Infinity"

然而

eval('4*1').toPrecision(10)
// Output: "4.000000000"

如何修剪尾随零还要保持上面的漂亮输出?

【问题讨论】:

  • numb = (Math.round(numb * 100000000)) / 100000000);
  • 谢谢大家,但这两个建议都只涵盖了第二个和第三个例子,但现在第一个例子产生“2083619852000000”而不是“2.083619852e+15”
  • 确保expression 是由而不是由第三方生成的。也就是说,读取输入并根据它生成expression,因为eval() on unsafe code is unsafe

标签: javascript math precision


【解决方案1】:

使用 toPrecision 后除以 1。 Javascript 将跟踪零,并且不需要正则表达式。

【讨论】:

  • 我这样使用这个解决方案:val.toFixed(2) / 1
  • 这是有效的,因为在 javascript 中,字符串和数字之间的除法返回一个数字类型,如果你乘以 1,同样适用
  • 我认为这是大多数人(不是 OP)可能想要的答案。例如:eval('456456+45646486*45646884').toPrecision(10) == 2.083619852e+15 就像 op 想要的那样,但是将其转换为一个数字 (/1) 会产生主观上更丑陋的2083619852000000
  • 这实际上非常有效。
  • 奇怪的解决方案,但它有效
【解决方案2】:

只有全零小数

  eval('4*1').toPrecision(10).replace(/\.0+$/,"")

零结尾小数:

  eval('4.5*1').toPrecision(10).replace(/\.([^0]+)0+$/,".$1")

编辑:处理所有零和结束零的情况

编辑:如果您总是首先使用 .toPrecision(),因此总是有一个“。”,您可以修剪掉任何尾随零:

  eval('4.5*1').toPrecision(10).replace(/0+$/,"")

编辑:处理尾随小数:

eval('4.5*0').toPrecision(10).replace(/\.?0+$/,"")

【讨论】:

  • 差不多,但eval('4+0.0001').toPrecision(10).replace(/\.0+$/,"") 给出的是“4.000100000”而不是“4.0001”
  • 明白了,为此添加了另外两个选项。如果需要更复杂的东西,请告诉我。
  • 正则表达式来拯救?我认为最后一次编辑成功了!我会给它一个更彻底的测试并接受它是否很好去!非常感谢。
  • 对整数有什么改进吗?即“2”而不是“2.”?
  • @greg:添加到答案。我认为最后一个是那个,感觉很好......
【解决方案3】:

以下 replace() 调用将替换所有尾随 0s 和尾随 .(如果存在):

eval(expression).toPrecision(10).replace(/(?:\.0+|(\.\d+?)0+)$/, "$1")

它是如何工作的?

/(?:\.0+|(\.\d+?)0+)$/ 在字符串末尾 ($) 查找 \.0+(\.\d+?)0+?: 防止 \.0+|(\.\d+?)0+ 成为 "captured"

\.0+ 将匹配 . 后跟任意数量的 0s。

(\.\d+?)0+ 将匹配 . 后跟至少一位数字后跟至少一位 0? 确保 0+ 匹配尽可能多的 0s。括号“捕获”非0s。

replace() 的第二个参数是替换匹配内容的新字符串。 $1 是一个变量,它告诉replace() 用第一个捕获的值替换匹配的值(因为1$ 之后)。在这种情况下,第一个捕获的值是 \.\d+? 匹配的值。

所以,最后:

  1. . 后跟任意数量的 0s 将被丢弃
  2. . 后跟非0s 后跟0s 将丢弃0s

示例

有关.40*14*140*1123 精度的方法比较,请参见下文。每组中的第一个(粗体)项目是这种方法。红色项目是那些不符合预期的项目。

var tests = [
  '.04*1',
  '.40*1',
  '4*1',
  '40*1'
];
var results = {};
for (var i = 0; i < tests.length; i += 1) {
  results[i] = {};
  for (var p = 1; p < 3; p += 1) {
    results[i][p] = {};
    results[i][p][0] = {
      'output': eval(tests[i]).toPrecision(p).replace(/(?:\.0+|(\.\d+?)0+)$/, "$1"),
      'regex': '/(?:\.0+|(\.\d+?)0+)$/, "$1"'
    };
    results[i][p][1] = {
      'output': eval(tests[i]).toPrecision(p).replace(/\.0+$/, ""),
      'regex': '/\.0+$/, ""'
    };
    results[i][p][2] = {
      'output': eval(tests[i]).toPrecision(p).replace(/\.([^0]+)0+$/, ".$1"),
      'regex': '/\.([^0]+)0+$/, ".$1"'
    };
    results[i][p][3] = {
      'output': eval(tests[i]).toPrecision(p).replace(/0+$/, ""),
      'regex': '/0+$/, ""'
    };
    results[i][p][4] = {
      'output': eval(tests[i]).toPrecision(p).replace(/\.?0+$/, ""),
      'regex': '/\.?0+$/, ""'
    };
  }
}
for (var i in results) {
  $("#result").append("<h1>" + tests[i] + "</h1>");
  for (var p in results[i]) {
    var expected = null;
    for (var t in results[i][p]) {
      var div = $("<div></div>");
      if (t == 0) {
        expected = results[i][p][t].output;
        div.addClass("expected");
      } else if (results[i][p][t].output !== expected) {
        div.addClass("invalid");
      }
      div.append("P" + p + ": " + results[i][p][t].output);
      div.append(" <small>" + results[i][p][t].regex + "</small>");
      $("#result").append(div);
    }
    $("#result").append("<br>");
  }
}
body { font-family: monospace; }
.expected { font-weight: bold; }
.invalid { color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="result"></div>

【讨论】:

  • 简单地使用 $2 而不是 $1 会比非捕获组更简单并且运行得更快。
  • @dandavis “Simplfy”是主观的。在处理复杂的正则表达式时,我发现从长远来看,只有捕获您实际要使用的组才能大大简化事情。这不是我found with some experimenting 的内容。是的,在 Chrome 37 中,使用捕获组更快,但无论使用何种方法,Firefox 33 似乎都表现得一样好。而且,我运行了几次测试,Firefox 在非捕获组中的表现更好
猜你喜欢
  • 2020-08-16
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
相关资源
最近更新 更多