Nice programing

왜 많은 (오래된) 프로그램이 round (input) 대신 floor (0.5 + input)를 사용합니까?

nicepro 2020. 10. 7. 08:16
반응형

왜 많은 (오래된) 프로그램이 round (input) 대신 floor (0.5 + input)를 사용합니까?


차이점은 다음 코드 와 같이 내가 믿는 타이 브레이킹에 대한 입력을 제공하는 반환 값에 있습니다 .

int main()
{
    std::cout.precision(100);

    double input = std::nextafter(0.05, 0.0) / 0.1;
    double x1 = floor(0.5 + input);
    double x2 = round(input);

    std::cout << x1 << std::endl;
    std::cout << x2 << std::endl;
}

다음을 출력합니다.

1
0

그러나 그들은 결국 다른 결과 일뿐이며 선호하는 것을 선택합니다. 내가 사용하는 "오래된"C / C ++ 프로그램을 많이 볼 floor(0.5 + input)대신을 round(input).

역사적인 이유가 있습니까? CPU에서 가장 저렴합니까?


std::roundC ++ 11에 도입되었습니다. 그 전에는 std::floor프로그래머가 사용하고 있었기 때문에 사용할 수있었습니다.


역사적 이유는 전혀 없습니다. 이런 종류의 일탈은 해마다 존재했습니다. 사람들은 아주, 아주 장난 스러울 때 이렇게합니다. 이것은 부동 소수점 산술의 심각한 남용이며 많은 경험 많은 전문 프로그래머가 그것에 속합니다. Java bods도 버전 1.7까지 수행했습니다. 웃긴 녀석들.

내 추측은 괜찮은 기본 독일어 반올림 기능은 C ++ 11 (C가 C99에서 C를 가져 왔음에도 불구하고)까지는 공식적으로 사용할 수 없었지만 실제로는 소위 대안을 채택한 변명이 아닙니다.

문제는 다음과 같습니다. floor(0.5 + input) 항상 해당 std::round호출 과 동일한 결과를 복구하지는 않습니다 !

그 이유는 매우 미묘합니다. a.5정수에 대한 독일어 반올림의 컷오프 포인트 a는 우주의 우연한 속성에 의해 이원 적 합리적 입니다. 이것은 IEEE754 부동 소수점에서 2의 52 제곱까지 정확하게 표현할 수 있으며 그 이후에는 반올림이 아무렇게나 std::round작동하지 않으므로 항상 제대로 작동합니다. 다른 부동 소수점 체계에 대해서는 설명서를 참조하십시오.

그러나에 추가 0.5하면 double일부 값에 대해 약간의 언더 슈트 또는 오버 슈트를 유발하는 부정확성이 발생할 수 있습니다. 생각해 보면 두 개의 double값을 함께 더하는 것, 즉 무의식적 인 부정 변환의 시작입니다. 그리고 입력의 매우 강력한 함수 (예 : 반올림 함수)를 적용하는 것은 눈물로 끝날 수밖에 없습니다.

하지마 .

참조 : Math.round (0.49999999999999994)가 1을 반환하는 이유


나는 이것이 당신이 실수하는 곳이라고 생각합니다.

그러나 그들은 결국 다른 결과 일뿐이며 선호하는 것을 선택합니다. round (input) 대신 floor (0.5 + input)를 사용하는 "오래된"C / C ++ 프로그램이 많이 있습니다.

그것은 사실이 아닙니다. 도메인에 적합한 반올림 체계를 선택해야 합니다 . 금융 애플리케이션에서는 은행가의 규칙을 사용하여 반올림합니다 (부동산을 사용하지 않음). 그러나 샘플링 할 때를 사용하여 반올림 static_cast<int>(floor(f + .5))하면 샘플링 노이즈가 줄어들고 동적 범위가 증가합니다. 픽셀을 정렬 할 때, 즉 위치를 화면 좌표로 변환 할 때 다른 반올림 방법을 사용하면 구멍, 간격 및 기타 아티팩트가 생성됩니다.


간단한 이유는 숫자를 반올림하는 방법이 다르기 때문에 사용한 방법을 알지 못하면 다른 결과를 얻을 수 있기 때문입니다.

floor ()를 사용하면 결과와 일치 할 수 있습니다. float가 .5 이상이면 추가하면 다음 정수로 올라갑니다. 그러나 .49999는 소수만 떨어 뜨립니다.


많은 프로그래머가 다른 언어로 프로그래밍 할 때 배운 관용구를 적용합니다. 모든 언어에 round()기능 이있는 것은 아니며 이러한 언어에서는 floor(x + 0.5)대체로 사용 하는 것이 일반적 입니다. 이러한 프로그래머가 C ++를 사용하기 시작하면 항상 내장 된 .NET Framework가 있다는 것을 깨닫지 못하고 round()익숙한 스타일을 계속 사용합니다.

즉, 무언가를하는 코드가 많다고해서 그럴만 한 이유가 있다는 의미는 아닙니다. 모든 프로그래밍 언어에서 이에 대한 예를 찾을 수 있습니다. 철갑 상어의 법칙을 기억하십시오 :

모든 것의 90 %는 쓰레기

참고 URL : https://stackoverflow.com/questions/47302544/why-do-lots-of-old-programs-use-floor0-5-input-instead-of-roundinput

반응형