>  기사  >  백엔드 개발  >  C 부동 소수점 연산이 예상치 못한 결과를 생성하는 이유는 무엇이며, 이러한 정밀도 이상 현상을 어떻게 완화할 수 있습니까?

C 부동 소수점 연산이 예상치 못한 결과를 생성하는 이유는 무엇이며, 이러한 정밀도 이상 현상을 어떻게 완화할 수 있습니까?

Barbara Streisand
Barbara Streisand원래의
2024-11-04 21:38:02814검색

Why does C   floating-point arithmetic produce unexpected results, and how can we mitigate these precision anomalies?

C 부동 소수점 정밀도 이상 및 분해능

광범위한 사용에도 불구하고 C의 부동 소수점 숫자는 정밀도에 한계가 있습니다. 다음 코드 조각을 고려해 보세요.

<code class="cpp">double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;

이 코드는 예상되는 0.3 대신 0.2999999999999999889를 출력합니다. 이러한 불일치는 변수 a가 정확히 0.3 배정밀도 부동 소수점 숫자로 저장되지 않고 오히려 부동 소수점 값의 유한한 표현으로 인해 이에 대한 근사값으로 저장되기 때문에 발생합니다.

더 놀라운 동작은 다음과 같은 경우에 발생합니다. a가 50번 반복적으로 추가됩니다.

<code class="cpp">double a, b;
a = 0.3;
b = 0;
for (char i = 1; i <= 50; i++) {
  b = b + a;
};
std::cout.precision(20);
std::cout << b << std::endl;

이 코드는 놀랍게도 15.0 대신 15.000000000000014211을 출력합니다. 덧셈을 할 때마다 근사 오차가 누적되어 원래의 정밀도보다 큰 오차가 누적되기 때문입니다.

정밀도 이상 해결

정확한 결과를 얻으려면 숫자 유형에 사용 가능한 숫자보다 더 큰 출력 정밀도를 설정하지 않으려면 매우 중요합니다. 이는 std::numeric_limits 클래스를 사용하여 달성할 수 있습니다:

<code class="cpp">#include <iostream>
#include <limits>
int main()
{
        double a = 0.3;
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << a << std::endl;
        double b = 0;
        for (char i = 1; i <= 50; i++) {
                  b = b + a;
        };
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << b << std::endl;
}</code>

이 코드는 digits10 멤버 함수를 사용하여 정밀도를 배정밀도 부동 소수점 숫자에 사용할 수 있는 최대 자릿수인 15로 설정합니다.

부동 소수점 연산의 한계

제공된 솔루션은 정밀도 오류를 최소화하지만 부동 소수점 연산에는 고유한 한계가 있음을 인식하는 것이 중요합니다. . 루프에 수천 번의 반복이 포함되면 정밀도가 적절하게 설정되어 있어도 누적된 오류가 심각해질 수 있습니다. 이러한 시나리오에서는 고정 소수점 숫자 또는 유리수와 같은 대체 데이터 유형이 정확한 값을 유지하는 데 더 적합할 수 있습니다.

위 내용은 C 부동 소수점 연산이 예상치 못한 결과를 생성하는 이유는 무엇이며, 이러한 정밀도 이상 현상을 어떻게 완화할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.