Дозвольте констатувати очевидний кулак: я повністю розумію, що типи з плаваючою комою не можуть точно представляти десяткові значення . Це не про це! Тим не менше, розрахунки з плаваючою комою повинні бути детермінованими .
Тепер, коли це не в змозі, дозвольте показати вам цікавий випадок, який я спостерігав сьогодні. У мене є список значень з плаваючою комою, і я хочу їх підсумувати:
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
Поки що так добре - сюрпризів тут немає. Всі ми знаємо, що 1.2
не можна точно представити у бінарному поданні, тому очікується "неточний" результат.
Тепер наступне дивне, що відбувається, коли я вийшов - приєднався до іншої таблиці:
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 , ви також можете побачити план виконання)
У мене однакова сума над тими ж значеннями, але інша помилка з плаваючою комою. Якщо додати до таблиці більше рядків #A
, ми можемо побачити, що значення чергується між цими двома значеннями. Мені вдалося відтворити це питання лише за допомогою LEFT JOIN
; INNER JOIN
працює як очікується тут.
Це незручно, тому що це означає , що DISTINCT
, GROUP BY
або PIVOT
бачить їх як різні значення (які насправді , як ми виявили , це питання).
Очевидним рішенням є округлення значення, але мені цікаво: чи є логічне пояснення такої поведінки?