计算具有相同精度的两个数字的平均值

时间:2013-01-30 16:05:51

标签: javascript average

我需要计算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上找到以前的解决方案。

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

您需要使用函数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:link

答案 2 :(得分:1)

javascript中的数字都是IEEE754定义的双精度浮点数。这意味着在基数10中没有定义点位置,并且您总能找到精度似乎不是您想要的那些情况。

解决方案是

  • 不使用js数字进行计算。这个解决方案很重,通常没用。
  • 在需要显示时将数字格式化为字符串(仅限于此时)。您可以使用to Fixed or toPrecision

有用的读物​​:What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 3 :(得分:1)

您可以使用所用数字的'precision'来判断返回值的适当精确度。

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

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

* /

答案 4 :(得分:0)

您可以使用Number.toPrecision(digits)来执行此操作。