【问题标题】:Javascript - Most efficient way to round off float to nearest non-zero numberJavascript - 将浮点数舍入到最接近的非零数的最有效方法
【发布时间】:2016-11-28 10:40:00
【问题描述】:

我想用(至少)2 位有效数字对 Javascript 中的浮点数进行四舍五入。

例如,具有以下期望的结果:

roundOff(0.000000001124)  // 0.0000000011 or 1.1e-9 (both acceptable)
roundOff(1.423421)  // 1.42
roundOff(0.00053245)  // 0.00053
roundOff(422.243224)  // 422.24
roundOff(422.0000000123)  // 422.00

我知道我可以使用对数和四舍五入来做类似here 中提到的事情,但它会舍入更大的数字,例如-123.0 -> -100

任何聪明的基于 Javascript 的解决方案?

【问题讨论】:

  • 您的问题不清楚。你需要多少个有效数字?你到底想做什么?
  • 更新了问题。

标签: javascript algorithm floating-point rounding logarithm


【解决方案1】:

如果我理解正确,您需要一个函数,它为绝对值小于 1 的数字返回两位有效数字,或者为绝对值大于 1 的数字返回两位小数。

我还是不明白为什么你认为0.000000001124 应该四舍五入为0.0000000012。你的意思是写0.0000000011 吗?

如果是这样,这个函数应该做你想做的:

function roundOff(n) {
  return parseFloat(n.toExponential(Math.max(1,2+Math.log10(Math.abs(n)))));
}

示例:

var a = new Array(0.000000001124, 1.423421, 0.00053245, 422.243224,
                  422.0000000123, 123, -123);
for (i=0; i<7; i++) console.log(roundOff(a[i]));

输出:

1.1e-9
1.42
0.00053
422.24
422
123
-123

【讨论】:

  • 对于 12 和 11 的混淆感到抱歉。我已经在原始问题中修复了它。现在试试你的方法。
  • 太棒了!奇迹般有效。 :)
【解决方案2】:

以下函数在 '.' 后有 2 个有效数字时对给定数字进行四舍五入。出现。它执行输入验证并根据第三个有效数字舍入第二个有效数字。

function roundOff(number) {
  var temp = "" + number,
      counterTwoFigures = 0,
      roundedNumber = '',
      startingIndex = temp.indexOf('.'),
      maxDecimalsAllowance = 20,
      multiplier = 100,
      minimumThreshold = 1;


  if(number * multiplier < minimumThreshold) {
    temp = parseFloat(temp).toFixed(maxDecimalsAllowance);
  }

  if(isNaN(number)){
    return undefined;
  }
  
  if(startingIndex === -1) {
    return number;
  }

  roundedNumber = temp.substring(0, startingIndex);

  for(var i = startingIndex, len = temp.length; i < len; i++){

    if((parseFloat(temp[i]) > 0)) {
      counterTwoFigures++;
    }

    if(counterTwoFigures > 2){
      if(temp[i] >= 5) {
        var updateNumber = "" + (parseFloat(roundedNumber[roundedNumber.length-1]) + 1);
        var positionToUpdate = roundedNumber.length-2;
        var initialString = roundedNumber.substr(0, roundedNumber.length - 1);
        roundedNumber = initialString + updateNumber;
        break;
      } else {
        break;
      }
    }

    roundedNumber += temp[i];
  }
  
  return parseFloat(roundedNumber);
}

var a = new Array(0.000000001124, 1.423421, 0.00053245, 422.243224,
              422.0000000123, 123, -123, 0.687);
for (i=0; i<a.length; i++) console.log('Input: ' + a[i] + ', Output: ' + roundOff(a[i]));

【讨论】:

  • roundOff(0.000000001124) == 1.12 — 这肯定不对吧?
  • 该错误是由于数字 0.000000001124 被自动转换为科学计数法所致。由于我将其转换为字符串,因此该算法假设 1.12e-9 将转换为 1.12(根据要求,在两个有效数字之后)。我添加了一个验证并将 toFixed 应用于高于 0.01 且低于 1e-20 的数字(这是应用 .toFixed() 的下限)。
  • 好的,这样更好。但是roundOff(6.789) 不应该是6.79 吗?你的函数返回6.78
  • 我已经更新了解决方案,根据第 3 个数字的值替换了第 2 个有效数字:如果值高于 5,则第 2 个数字加一。
  • 很抱歉打扰了,但是roundOff(0.1001) == 0.10,确定吗?你的函数返回0.1001
猜你喜欢
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多