비 결정적 수레


10

명백한 주먹을 말하겠습니다 : 부동 소수점 유형은 정확하게 10 진수 값을 나타낼 수 없다는 것을 완전히 이해합니다 . 이것에 관한 것이 아닙니다! 그럼에도 불구하고 부동 소수점 계산은 결정 론적이어야 합니다.

이제이 방법이 중단되었으므로 오늘 관찰 한 호기심이 많은 사례를 보여 드리겠습니다. 부동 소수점 값의 목록이 있으며 그 값을 요약하고 싶습니다.

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 fiddle , 거기에서 실행 계획을 볼 수도 있습니다)

동일한 값에 대해 동일한 합계가 있지만 부동 소수점 오류가 다릅니다 . table에 행을 더 추가하면 두 값 사이에서 값이 번갈아 나타납니다. 이 문제는 다음과 같이 재현 할 수 없었습니다 . 여기 예상대로 작동합니다.#ALEFT JOININNER JOIN

그것이 있다는 것을 의미하기 때문에, 불편 DISTINCT, GROUP BY또는 PIVOT(우리는이 문제를 발견하는 방법을 실제로하는) 다른 값으로 그들을보고있다.

확실한 해결책은 가치를 반올림하는 것이지만 궁금합니다.이 행동에 대한 논리적 설명이 있습니까?

답변:


15

실제로, 당신이 말하는 링크는 부동 소수점 산술 계산이 항상 결정적이라고 말하지 않습니다. 실제로, 답변 중 하나에서 덧셈은 연관성이 아니며 (의미 (a + b) + c가 반드시 같을 필요는 없음 a + (b + c)) 언급되어 있으며이 답변 에서도 언급됩니다 .

스트림 집계가 각 그룹의 행을 다른 순서로 처리하는 경우 일반적으로 수행 할 수있는 SQL Server입니다. ORDER BY적절한 절이 없으면 옵티마이 저는 추가를 수행하는 순서에 관계없이 가장 빠른 스캔 또는 탐색 또는 다른 쿼리 연산자를 선택합니다. 그러면 관찰 한 동작을 설명 할 수 있습니다.

덧셈은 항상 결정적입니다. 동일한 두 개의 부동 소수점을 넣을 때 동일한 부동 소수점을 얻습니다. 그러나 다른 순서로 함께 float를 추가하면 다른 결과를 얻을 수 있습니다.


연관성은 결정론과 관련이 없으므로 비트가 오도됩니다.
Mooing Duck

부동 소수점 추가의 비 연관성은 SQL Server 집계 함수의 비 결정적 동작으로 이어집니다. SUM()@MooingDuck에 동의 하시겠습니까?
mustaccio

아니? 정수 부서는 분명한 반례입니다. 비연 관적이지만 완전히 결정적입니다. 마찬가지로 부동 소수점 나누기는 비연 관적이며 여전히 결정적이어야합니다. 이것으로부터 우리는 추가가 비 연관적이고 여전히 결정론적인 것이 합리적이라고 결론을 내립니다. 즉, 덧셈 순서가 결정적이지 않으면 결과도 결정적이지 않으므로 첫 번째 문장과 마지막 문장은 여전히 ​​그렇습니다.
Mooing Duck

정수 나누기는 SUM()부동 소수점 인수 에 대한 SQL Server의 반대 예입니다 .
mustaccio

1
정수 나누기는 비 연관적이고 결정적입니다. 따라서 산술 연산 연관성은 결정 성과 관련이 없습니다. 따라서 비 연관성은 SUM()결정론 과 관련이 없어야합니다. 나는 SUM결정적이지 않은 것으로 보이지만 관련성이 없기 때문에 연관성에 대한 언급을 제거해야합니다.
Mooing Duck
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.