Bueno
Angel_Cruijff:
Tengo que decirte que has descubierto un
BUG
-no famoso- de javascript. Y contra el que no podemos luchar. Lo único que se puede hacer es usar
Math.round(), o algo así.
El bug no se queda ahí, fallan muchas más cosas. Falla la suma de elementos decimales, falla la multiplicación... como ves o_O
¿Cuánto dirías que da
0.1*0.1? Exacto, da 0.010000000000000002.
Tampoco hay que ir tan lejos. ¿
0.2+0.1? Bien: 0.30000000000000004
En números enteros (integer) no he encontrado nada... Menos mal.
He hecho un pequeño script que revela que para multiplicaciones de números de una décima tenemos un montón de errores. Se apoya en multiplicar los números sumándolos (3*2 = 3+3), y comparar esos dos resultados.
Código:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<meta http-equiv="Content-type" content="text/html;charset=iso-8859-1" />
<meta name="Author" content="derkeNuke" />
<title>Bug de Math en javascript</title>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
<!--
// escribir en el documento una ristra (x)html fuera de tiempo de ejecución.
function e(q,sinBR) {
var elDIV = document.createElement("DIV");
if(q==undefined) q="";
if(!sinBR) q+="<br/>";
elDIV.innerHTML = q;
for(var a=0; elDIV.childNodes.length>a; a++) {
document.body.appendChild( elDIV.childNodes[a].cloneNode(true) );
}
}
// Si x = 0.04 nos devuelve [4, 100]. El número en entero y el multiplicador necesario para ello.
function aEntero(x) {
var multiplicador = 1;
while( x!=parseInt(x) ) {
multiplicador *= 10;
// corremos la coma 1 posicion
x = Number( x.toString().replace(/(\.)(\d)/, "$2$1") );
}
return [x, multiplicador];
}
// Multiplicación manual: Multiplica dos números sumando y veces el x
function m(x,y) {
x = aEntero(x);
y = aEntero(y);
var mult = x[1] * y[1];
for(var i=0, r=0; i<y[0]; i++)
r+=x[0];
return r/mult;
}
// Compara la multiplicación nativa con la manual, devuelve true si no son iguales (si hay bug)
function hayBug(x,y) {
var mult = (x*y);
var bien = m(x,y);
var o = [ (mult!=bien), bien, mult ];
o.toString = function() { return this[0]; }
return o;
}
// Bucle principal
for(var i=0; i<1; i+=0.1, i=Math.round(i*10)/10 ) {
for(var j=0; j<1; j+=0.1, j=Math.round(j*10)/10 ) {
var b = hayBug(i,j);
if( b[0] ) {
e( i+"*"+j+" = "+ b[1] +", pero da "+b[2] );
}
}
e();
}
// -->
</script>
</body>
</html>
Bueno, no sé si posteé sobre esto hace tiempo, no lo he encontrado -de todas maneras no habría tenido respuestas, me acordaría- pero si alguien sabe de este tema, o de sitios donde hablen de ello y la 'regla' que lo produce, que lo postee por favor.
A estas alturas y con bugs tan gordos...
Un saludo y a ver si se agregan más detalles de ésto