Hemos encontrado un problema con Math.round () en JavaScript. El problema es que esta función no se redondea correctamente para números negativos. Por ejemplo :

1.5 ~ = 2

0.5 ~ = 1

-0.5 ~ = 0 // Incorrecta

-1.5 ~ = -1 // Incorrecta

Y esto no es correcto según el redondeo aritmético. Los números correctos para -0.5 deberían ser -1 y -1.5 deberían ser -2.

¿Existe alguna forma estándar de redondear correctamente los números negativos en Javascript?

9
Adrián Paníček 11 ene. 2017 a las 12:18

4 respuestas

La mejor respuesta

Puede guardar el letrero y solicitarlo más tarde, en ES5;

function round(v) {
    return (v >= 0 || -1) * Math.round(Math.abs(v));
}

console.log(round(1.5));  //  2
console.log(round(0.5));  //  1
console.log(round(-1.5)); // -2
console.log(round(-0.5)); // -1
9
Nina Scholz 11 ene. 2017 a las 09:37
var r = (Math.random() * 200) - 100;

¿Qué hay de evaluar puramente el resultado sin usar la biblioteca matemática? por ejemplo, al usar un operador ternario, puede verificar con elegancia los números negativos y luego el piso después del "redondeo":

var n = r + (r < 0 ? -0.5 : 0.5) | 0;

El | 0 es solo un truco tonto en js que "sobrecarga" al operador binario (puede usar cualquier operador binario) para truncar el número.

Tenga en cuenta que esto no es piso (como Math.floor), ya que Math.floor(-3.2), por ejemplo, en realidad producirá -4.


Incluso se podría hacer algo similar a la respuesta de @ Balan (me gusta esa y la siguiente, pero siento que esto o que el operador ternario será un poco más rápido; sin embargo, probablemente me equivoque, porque {{X0} } las bibliotecas han demostrado ser muy rápidas):

var n = (r + Math.sign(r) / 2) | 0;

Probablemente la forma más rápida y elegante:

var n = Math.floor(r + 0.5);

Ejemplo:

var body = document.getElementById("myTable").children[1];
var i, iMax = 100, r, tr, td;
for (i = 0; i < iMax; i++) {
    r = Math.random() * 200 - 100;
    tr = document.createElement("tr");
    td = document.createElement("td");
    td.innerHTML = r;
    tr.appendChild(td);
    td = document.createElement("td");
    td.innerHTML = (r + Math.sign(r) / 2) | 0;
    tr.appendChild(td);
    body.appendChild(tr);
}
#myTable {
    min-width: 250px;
}
<table id="myTable">
 <thead>
  <tr>
   <th>float</th>
   <th>round</th>
  </tr>
 </thead>
 <tbody>
 </tbody>
</table>
0
dylnmc 7 ago. 2018 a las 20:39

Aplique Math.round después de convertir a un número positivo y finalmente retroceda el letrero. Donde puede usar Math.sign método para obtener el signo del número y {{X2} } para obtener el absoluto del número.

console.log(
  Math.sign(num) * Math.round(Math.sign(num) * num),
  // or
  Math.sign(num) * Math.round(Math.abs(num))
)
var nums = [-0.5, 1.5, 3, 3.6, -4.8, -1.3];

nums.forEach(function(num) {
  console.log(
    Math.sign(num) * Math.round(Math.sign(num) * num),
    Math.sign(num) * Math.round(Math.abs(num))
  )
});
16
Pranav C Balan 11 ene. 2017 a las 09:28

Puede intentar usar Math.ceil (num) para redondear num y luego - 1 si num fue negativo, p. Ej.

if (num < 0) {
  num = Math.ceil(num) - 1;
} else {
  num = Math.ceil(num);
}
1
PAH 30 ene. 2019 a las 12:03