Nicht deterministische Summe von Floats

10

Lassen Sie mich die offensichtliche Faust sagen: Ich verstehe vollkommen, dass Gleitkommatypen Dezimalwerte nicht genau darstellen können . Hier geht es nicht darum! Dennoch sind Fließkommaberechnungen soll deterministisch sein .

Nun, da dies nicht im Weg ist, möchte ich Ihnen den merkwürdigen Fall zeigen, den ich heute beobachtet habe. Ich habe eine Liste von Gleitkommawerten und möchte sie zusammenfassen:

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

So weit, so gut - keine Überraschungen hier. Wir alle wissen, dass 1.2dies nicht genau in binärer Darstellung dargestellt werden kann, daher wird das "ungenaue" Ergebnis erwartet.

Nun passiert Folgendes Seltsames, wenn ich mich einer anderen Tabelle anschließe:

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

( SQL Geige , Sie können dort auch den Ausführungsplan sehen)

Ich habe die gleiche Summe über die gleichen Werte, aber einen anderen Gleitkommafehler. Wenn ich der Tabelle weitere Zeilen hinzufüge #A, können wir sehen, dass der Wert zwischen diesen beiden Werten wechselt. Ich konnte dieses Problem nur mit a reproduzieren LEFT JOIN; INNER JOINfunktioniert hier wie erwartet.

Dies ist unbequem, weil es bedeutet , dass ein DISTINCT, GROUP BYoder PIVOTsieht sie als unterschiedliche Werte (was eigentlich ist , wie wir dieses Problem entdeckt).

Die offensichtliche Lösung besteht darin, den Wert zu runden, aber ich bin neugierig: Gibt es eine logische Erklärung für dieses Verhalten?

Heinzi
quelle

Antworten:

15

Tatsächlich besagt der Link, auf den Sie sich beziehen, nicht, dass Gleitkomma-Arithmetikberechnungen immer deterministisch sind. Tatsächlich wird in einer der Antworten erwähnt, dass Addition nicht assoziativ ist (was (a + b) + cnicht unbedingt gleichbedeutend ist a + (b + c)), was auch in dieser Antwort gesagt wird .

Wenn die Stream-Aggregation die Zeilen jeder Gruppe in unterschiedlicher Reihenfolge verarbeitet, kann SQL Server dies normalerweise tun. Wenn ORDER BYdie entsprechende Klausel keine enthält , wählt der Optimierer aus, welcher Scan- oder Such- oder andere Abfrageoperator am schnellsten ist, unabhängig davon, in welcher Reihenfolge die Ergänzungen ausgeführt werden. Dies könnte das beobachtete Verhalten erklären.

Die Addition ist immer deterministisch: Wenn Sie dieselben zwei Floats einsetzen, erhalten Sie denselben Float heraus. Das Hinzufügen von Floats in einer anderen Reihenfolge kann jedoch zu einem anderen Ergebnis führen.

Ross Presser
quelle
Assoziativität hat keine Beziehung zum Determinismus, so dass dieses Bit irreführend ist.
Mooing Duck
Die SUM()Nichtassoziativität der Gleitkommaaddition führt zu einem nicht deterministischen Verhalten der SQL Server-Aggregatfunktion. Würden Sie @MooingDuck zustimmen?
Mustaccio
Nein? Integer Division ist ein klares Gegenbeispiel. Es ist nicht assoziativ, aber völlig deterministisch. Ebenso sollte die Gleitkommadivision nicht assoziativ und dennoch deterministisch sein. Daraus schließen wir, dass es vernünftig ist, dass Addition nicht assoziativ und dennoch deterministisch ist. Wenn jedoch die Reihenfolge der Additionen nicht deterministisch ist, ist das Ergebnis ebenfalls nicht deterministisch, sodass Ihr erster und letzter Satz unabhängig davon immer noch korrekt sind.
Mooing Duck
Die Ganzzahldivision ist ein Gegenbeispiel für den SQL Server SUM()über Gleitkomma-Argumente. Wie genau?
Mustaccio
1
Die Ganzzahldivision ist nicht assoziativ und deterministisch. Daher ist die Assoziativität arithmetischer Operationen nicht mit Determinismus verbunden. Daher muss jede Nichtassoziativität von SUM()für ihren Determinismus irrelevant sein. Ich stimme zu, dass SUMdies nicht deterministisch zu sein scheint, aber Sie sollten Assoziativitätserwähnungen entfernen, da dies nichts damit zu tun hat.
Mooing Duck