Permítanme decir el puño obvio: entiendo completamente que los tipos de coma flotante no pueden representar con precisión los valores decimales . ¡Esto no se trata de eso! Sin embargo, se supone que los cálculos de coma flotante son deterministas .
Ahora que esto está fuera del camino, déjame mostrarte el curioso caso que observé hoy. Tengo una lista de valores de punto flotante y quiero resumirlos:
CREATE TABLE #someFloats (val float);
INSERT INTO #someFloats (val) VALUES (1), (1), (1.2), (1.2), (1.2), (3), (5);
SELECT STR(SUM(#someFloats.val), 30, 15) FROM #someFloats;
DROP TABLE #someFloats;
-- yields:
-- 13.600000000000001
Hasta ahora, todo bien, no hay sorpresas aquí. Todos sabemos que 1.2
no se puede representar exactamente en representación binaria, por lo que se espera el resultado "impreciso".
Ahora sucede lo siguiente extraño cuando me uní a otra mesa:
CREATE TABLE #A (a int);
INSERT INTO #A (a) VALUES (1), (2);
CREATE TABLE #someFloats (val float);
INSERT INTO #someFloats (val) VALUES (1), (1), (1.2), (1.2), (1.2), (3), (5);
SELECT #A.a, STR(SUM(#someFloats.val), 30, 15)
FROM #someFloats LEFT JOIN #A ON 1 = 1
GROUP BY #A.a;
DROP TABLE #someFloats;
DROP TABLE #A;
-- yields
-- 1 13.600000000000001
-- 2 13.599999999999998
( violín sql , también puedes ver el plan de ejecución allí)
Tengo la misma suma sobre los mismos valores, pero un error de punto flotante diferente . Si agrego más filas a la tabla #A
, podemos ver que el valor alterna entre esos dos valores. Solo pude reproducir este problema con un LEFT JOIN
; INNER JOIN
Funciona como se espera aquí.
Esto es inconveniente, porque significa que a DISTINCT
, GROUP BY
o los PIVOT
ve como valores diferentes (que es así como descubrimos este problema).
La solución obvia es redondear el valor, pero tengo curiosidad: ¿hay una explicación lógica para este comportamiento?