Преобразование математического уравнения из PHP в Javascript (Jquery) - PullRequest
0 голосов
/ 05 августа 2011

Я работал над получением уравнения коэффициента вариации, портированного с PHP на Javascript, но не могу заставить его работать.

Оригинальный скрипт PHP:

// define variables, strip spaces
$weights = $_POST['weights'];
// define coefficient of variation function
function cv($array){
    $n = 0;
    $mean = 0;
    $M2 = 0;
    foreach($array as $x){
        if ($x != NULL AND $x != '') {
            $n++;
            $delta = $x - $mean;
            $mean = $mean + $delta/$n;
            $M2 = $M2 + $delta*($x - $mean);
            $total = $total + $x;
        }
    }
    return (((sqrt($M2/($n - 1))) / ($total/$n))*100);
}
$cv = (cv($weights));

Это в основном берет массив и вычисляет коэффициент вариации для него.Теперь, когда я пытаюсь преобразовать его в Javascript с помощью некоторой функции Jquery:

var fields = $('#cvform').serializeArray();
        var count = 0;
        var num = 0;
        var mean = 0;
        var m2 = 0;
        var total = 0;
        var delta = 0;
        jQuery.each(fields, function(i, field){
        if (field.value > 0) {
            num++;
            delta=(field.value-mean);
            mean=(mean+delta/num);
            m2=(m2+delta*(field.value-mean));
            total=(total+field.value);
        };
        });
        var cov=(((Math.sqrt(m2/(num-1)))/(total/num))*100);
        $("<span>Coefficient of Variation: " + cov +  "</span>").appendTo('#cvdisplay');

Хотя функция javascript выводит ответ, это не правильно.Если я введу значения «3,3,2,3,3,4», PHP-скрипт выдаст результат 21,08, что правильно.Функция javascript дает мне значение 0.0011418432035849642.

Может кто-нибудь указать мне, где уравнения отличаются?

Ответы [ 5 ]

1 голос
/ 05 августа 2011

Проблема заключается в строке JavaScript total=(total+field.value);, которая приводит к 0332334 вместо 18, как ожидалось.Конкатенация строк применяется вместо числового сложения.

Это можно исправить, проанализировав целочисленное значение: total += parseInt(field.value);

1 голос
/ 05 августа 2011

Вам необходимо преобразовать значения вашего массива в числа с плавающей запятой через parseFloat() (или целые числа, parseInt(), что вам подходит):

var fields = $('#cvform').serializeArray();
var count = 0;
var num = 0;
var mean = 0;
var m2 = 0;
var total = 0;
var delta = 0;
$.each(fields, function(i, field) {
    alert(field.value);
    if (parseFloat(field.value) > 0) {
        num++;
        delta = (parseFloat(field.value) - mean);
        mean = (mean + delta / num);
        m2 = (m2 + delta * (parseFloat(field.value) - mean));
        total = (total + parseFloat(field.value));
    }
});
var cov = (((Math.sqrt(m2 / (num - 1))) / (total / num)) * 100);
$("<span>Coefficient of Variation: " + cov +  "</span>").appendTo('#cvdisplay');
0 голосов
/ 05 августа 2011

Здесь я немного изменил код и заставил его работать.Я в основном изолировал сегменты немного больше.Сделано это более прямым.

<?php
$weights = Array(3,3,2,3,3,4);

// define coefficient of variation function
function cv($array) {
  $n = 0;
  $mean = 0;
  $M2 = 0;
  $total = 0;

  foreach($array as $x) {
    if ( !empty($x) ) {
      $n++;
      $delta = $x - $mean;
      $mean = $mean + $delta / $n;
      $M2 = $M2 + $delta * ($x - $mean);
      $total = $total + $x;
    }
  }

  $sqrt = sqrt( $M2 / ($n - 1) );
  $tn = $total / $n;
  echo "Sqrt is $sqrt tn is $tn";

  return ( $sqrt / $tn ) * 100;
}

$cv = cv($weights);
?>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
  var fields = Array(3,3,2,3,3,4);
  var count = 0;
  var n = 0;
  var mean = 0;
  var m2 = 0;
  var total = 0;
  var delta = 0;

  jQuery.each(fields, function(i, field) {
    //var x = field.value;
    var x = 1 * field;

    if (x > 0) {
      n++;
      delta = (x - mean);
      mean = (mean + (delta / n));
      m2 = (m2 + delta * (x - mean));
      total = (total + x);
    };
  });

  var sqrt = Math.sqrt(m2 / (n - 1));
  var tn = total / n;
  var cov = ((sqrt / tn) * 100);
  console.log("Total is: "+ total);
  console.log("Sqrt is " + sqrt + " tn is " + tn + " cov is " + cov);

  $('#js').text("JS Output is: " + cov);
});
</script>
</head>
<body>
  <div>
    <div>PHP Output: <?=$cv;?></div>
    <div id="js"></div>
  </div>
</body>
</html>
0 голосов
/ 05 августа 2011
function stDeviation(array){
    var L= array.length,
    mean= array.reduce(function(a, b){
        return a+b;
    })/L,
    dev= array.map(function(itm){
        var tem= itm-mean;
        return tem*tem;
    });
    return Math.sqrt(dev.reduce(function(a, b){
        return a+b;
    })/L);
}

Math.mean= function(array){
    return array.reduce(function(a, b){ return a+b; })/array.length;
}
Math.stDeviation=function(array){
    var mean= Math.mean(array);
    dev= array.map(function(itm){return (itm-mean)*(itm-mean); });
    return Math.sqrt(dev.reduce(function(a, b){ return a+b; })/array.length);
}


var A2= [6.2, 5, 4.5, 6, 6, 6.9, 6.4, 7.5];
alert ('mean: '+Math.mean(A2)+'; deviation: '+Math.stDeviation(A2))
0 голосов
/ 05 августа 2011

Вот прямой перевод предоставленной вами функции. Вы должны передать массив чисел javascript, и он выдаст искомый результат (по крайней мере, согласно модульным тестам, написанным в Node.js). Вы должны выполнить преобразование типа (строка-в-массив) в другой функции, чтобы отделить ваши проблемы и облегчить анализ кода;

var CoV = function(ary) {
    var mean = 0,
        n = 0,
        m2 = 0,
        total = 0,
        delta;

    for(var i = 0, l = ary.length; i < l; i += 1) {
        n += 1;

        delta = ary[i] - mean;
        mean = mean + delta / n;
        m2 = m2 + delta * (ary[i] - mean)
        total = total + ary[i]
    }

    console.log(mean);
    console.log(m2);
    console.log(total);

    return ((Math.sqrt(m2/(i - 1))) / (total / i)) * 100;
};
...