IEEE가 제곱근을 포함한 모든 연산에 대해 올바른 반올림을 수행한다고 가정하려면 귀하가 작성한 표현식에 더하기 캐스팅을 더해 모든 입력에 대해 올바른 답을 제공하십시오.
다음은 비공식적 인 증거입니다. c
은 32 비트 부호없는 정수로 53 비트 유효 숫자로 부동 소수점 유형으로 변환되므로 1 + 8*(double)c
은 exact이고 sqrt(1 + 8*(double)c)
은 올바르게 반올림됩니다. 1 + sqrt(1 + 8*(double)c)
은 2**((32 + 3)/2) = 2**17.5
보다 작기 때문에 2
으로 나누기가 정확하기 때문에 마지막 기간이 2**((32 + 3)/2) = 2**17.5
보다 작 으면 1
보다 작고 따라서 (1 + sqrt(1 + 8*(double)c))/2
이 하나의 ulp 내에서 정확하기 때문에 하나의 ulp 내에서 정확합니다.
마지막 사업은 바닥입니다. 문제의 경우는 (1 + sqrt(1 + 8*(double)c))/2
을 정수로 반올림 한 것입니다. 이것은 sqrt(...)
이 홀수 정수로 올림하는 경우에만 발생합니다.sqrt
의 인수가 정수이기 때문에, 최악의 경우는 긍정적 인 홀수 정수 z
에 대한 sqrt(z**2 - 1)
처럼, 우리는 테일러 전개에 의해
z - sqrt(z**2 - 1) = z * (1 - sqrt(1 - 1/z**2)) >= 1/(2*z)
바인딩. z
이 2**17.5
보다 작기 때문에 가장 가까운 정수와의 갭은 이상이며 결과는 2**17.5
보다 작습니다. 즉,이 오류는 올바르게 반올림 된 sqrt
에서 발생할 수 없습니다.
Yakk의 단순화를 채택, 우리는 추가 검사없이
(uint32_t)(0.5 + sqrt(0.25 + 2.0*c))
를 작성할 수 있습니다.
'c'의 예상 범위는 무엇입니까? – phs
@phs 'c'는 32 비트 부호없는 정수라고 가정 할 수 있습니다. – becko
고맙습니다. 한 가지 더 궁금한 점이 있습니다. "효율성이 얼마나 효율적입니까?" 이미'O (1)'닫힌 폼을 찾았습니다. (실제로 쿼드 수식을 통해 아직 계수를 실행하지 않았다고 가정합니다.) 조금씩 복잡한 해킹을 찾고 있습니까? – phs