Suma no determinista de carrozas


10

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.2no 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 JOINFunciona como se espera aquí.

Esto es inconveniente, porque significa que a DISTINCT, GROUP BYo los PIVOTve 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?

Respuestas:


15

En realidad, el enlace al que te refieres no dice que los cálculos aritméticos de coma flotante sean siempre deterministas. De hecho, en una de las respuestas se menciona que la suma no es asociativa (el significado (a + b) + cno necesariamente es igual a + (b + c)), lo que también se dice en esta respuesta .

Si la agregación de flujo procesa las filas de cada grupo en un orden diferente, lo que SQL Server generalmente puede hacer libremente; Si no hay ninguna ORDER BYen la cláusula apropiada, entonces el optimizador elegirá cualquier exploración o búsqueda u otro operador de consulta que sea más rápido, independientemente del orden en que realice las adiciones, entonces esto podría explicar el comportamiento que observa.

La suma siempre es determinista: pones los mismos dos flotadores, obtienes el mismo flotador. Pero agregar flotadores juntos en un orden diferente puede dar un resultado diferente.


La asociatividad no tiene relación con el determinismo, por lo que ese bit es engañoso.
Mooing Duck

La no asociatividad de la adición de coma flotante conduce a un comportamiento no determinista de la función agregada de SQL Server SUM(), ¿estaría de acuerdo @MooingDuck?
mustaccio

¿No? La división de enteros es un claro contraejemplo. Es no asociativo, pero completamente determinista. Del mismo modo, la división de coma flotante debe ser no asociativa y aún determinista. A partir de eso, concluimos que es razonable que la suma sea no asociativa y aún determinista. Dicho esto, si el orden de las adiciones no es determinista, el resultado tampoco será determinista, por lo que su primera y última oración siguen siendo correctas independientemente.
Mooing Duck

La división de enteros es un contraejemplo para SQL Server SUM()sobre argumentos de coma flotante, ¿cómo exactamente?
mustaccio

1
La división entera es no asociativa y determinista. Por lo tanto, la asociatividad de operaciones aritméticas no está relacionada con el determinismo. Por lo tanto, cualquier no asociatividad de SUM()debe ser irrelevante para su determinismo. Estoy de acuerdo en que SUMparece no ser determinista, pero debe eliminar las menciones de asociatividad, ya que eso no está relacionado.
Mooing Duck
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.