0

我需要计算 JavaScript 中两个实数之间的中点(平均值)。数字的范围可以变化很大,通常在 10000 和 0.0001 之间。

天真的方法

(parseFloat(first) + parseFloat(second)) / 2

给了我不需要的精度错误,即

(1.1 + 0.1) / 2 = 0.6000000000000001

如何确保结果没有多余的小数位?我想,由于只有两个输入,因此结果最多需要比输入多一个小数位。所以,我需要:

 1000 and 3000 to return 2000 (without decimal spaces)
 1234.5678 and 2468.2468 to return 1851.4073
 0.001 and 0.0001 to return 0.00055
 10000 and 0.0001 to return 5000.00005
 0.1 and 1.1 to return 0.6

澄清一下:我知道所有关于精度错误以及为什么会发生这种情况。我需要的是一个简单的解决方法,但我一直无法在 SO 上找到以前的解决方案。

4

5 回答 5

3

您将要使用该功能toFixed()。这是您的代码的样子((1.1 + 0.1) / 2).toFixed(4);。4 是小数位数。

这是一个示例

var num1 = "123.456";
var num2 = "456.1235";
if (num1.split('.')[1].length > num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num1.split('.')[1].length+1);
else
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length+1);

记住输入是字符串,这就是为什么num1num2是字符串。

更新:这是您想要的结果的正确 if 语句。

var num1 = "123.456";
var num2 = "456.1235";
if (num1.split('.').length == 1) {
  if (num2.split('.').length == 1)
    var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(0);
  else
    var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length);
} else if (num2.split('.').length == 1)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length);
else if (num1.split('.')[1].length == num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length);
else if (num1.split('.')[1].length > num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num1.split('.')[1].length+1);
else if (num1.split('.')[1].length < num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length+1);

编辑我不得不改变它检查没有小数空格的数字的顺序。这是我为帮助测试而创建的 jsFiddle:链接

于 2013-01-30T16:12:33.833 回答
2

Javascript 中的数字具有toFixed(n)删除除 n 个小数位以外的所有数字的方法。但是,当您不知道您的数字是非常大还是非常小时,这并不是很有帮助。但是你可以做的是首先对数的 Math.floor() 以数字的 10 为底得到点前面的小数位数,将数字除以 10^places,执行toFixed(n)其中 n 是最大数位数,然后再乘以 10^places。

于 2013-01-30T16:19:48.593 回答
1

javascript 中的数字都是IEEE754定义的双精度浮点数。这意味着没有以 10 为底定义的点位置,并且您总是会发现精度似乎不是您想要的那些情况。

解决方案是

  • 不要使用 js 数字来进行计算。该解决方案很重且通常无用。
  • 当您需要显示它们时(并且仅在那时)将您的数字格式化为字符串。您可以使用to Fixed 或 toPrecision

有用的阅读:每个计算机科学家都应该知道的关于浮点运算的知识

于 2013-01-30T16:13:55.480 回答
1

您可以使用正在使用的数字的“精度”来判断返回值的适当精度。

此示例将任意数量的数字平均到其参数的最大精度。

Math.average= function(){
    var a= arguments, L= a.length, i= 0,
    total= 0, next, prec= [];
    if(L== 1) return +a[0];
    while(i<L){
        next= Number(a[i++]);
        total+= next;
        if(next!== Math.floor(next)){
            prec.push(String(next).split('.')[1].length);
        }
    }
    prec= Math.max.apply(Math, prec)+1;
    return +((total/L).toFixed(prec));
    // returns number after precision adjusted
}

/*

tests:
var n1= ;
Math.average(1.1, .01);
0.555

var n1= 1.0111, n2= .01;
Math.average(1.0111,  .01);
0.51055

var n1= 1.1, n2= .01, n3= 1, n4= 1.025;
Math.average(n1, n2, n3, n4)
0.7838

*/

于 2013-01-30T17:31:29.840 回答
0

您可以使用Number.toPrecision(digits)来做到这一点。

于 2013-01-30T16:26:00.357 回答