2009-03-03 6 views
32

나는 구문std :: floor 후에 int로 캐스트하면 올바른 결과가 보장됩니까?

int floor(double x); 

하지만 doublestd::floor 반환과 함께 floor 기능을하고 싶습니다.

static_cast <int> (std::floor(x)); 

올바른 정수를 제공 할 수 있는지 또는 오프라인별로 문제가있을 수 있나요? 그것은 효과가있는 것처럼 보이지만 확실히 알고 싶습니다.

보너스 포인트의 경우 도대체 std::floor은 왜 double을 반환합니까?

답변

25

double의 범위는 32 또는 64 비트 정수의 범위보다 길기 때문에 std::floordouble을 반환하는 이유입니다. int으로 캐스팅하는 것이 적절한 범위 내에있는 한 괜찮습니다. 그러나 double은 모든 64 비트 정수를 정확하게 나타낼 수 없으므로 정확도가 떨어질 때 오류가 발생할 수도 있습니다. double 연속 2 루타의 차이는 예, 거의 당신이 원하는 것을 1보다 큰

+0

이 올바른 범위에 있다면 그래서, 캐스트는 사양이을 (의미 뭔가를) 말하는가 어디 괜찮를? ? –

+0

음, 여기에 두 가지 작업이 있습니다 : std :: floor 및 cast. std :: floor는 정수를 반환하기위한 것이고 캐스팅은 정수 값으로 지정됩니다. std :: floor가 반환하는 한 진실로 정확한 정수 인 값, I ca 그것이 실패하는 것이 어떻게 의미가 있는지 보지 마라. –

+0

어떻게 바닥에서 정확한 정수가 아닌 값이 반환됩니까? 작은 double (ε << 1)의 경우 floor (x)를 포함한 모든 정수 값을 나타낼 수 있습니다. 큰 double (엡실론 >> 1)의 경우, 정수 값만 나타낼 수 있으므로 floor (x) == x. – MSalters

12
static_cast <int> (std::floor(x)); 

되도록합니다. 그것은 당신에게 가장 가까운 정수를 제공하며, -infinity로 반올림됩니다. 적어도 입력이 int로 표현할 수있는 범위 내에있는 한. '.5 등을 추가하면 무슨 뜻인지 잘 모르겠지만 동일한 효과는 없습니다.

std :: floor는 가장 일반적인 이유 때문에 double을 반환합니다. 때로는 float 또는 double을 반올림하고 유형을 유지하려고 할 수 있습니다. 즉, 1.3f에서 1.0f로 반올림되어 1이 아닌

std :: floor가 int를 반환하면 어렵습니다. (또는 적어도 당신은 물건을 느리게하는 거기에서 여분의 불필요한 던지기를 가질 것이다).

바닥이 유형을 변경하지 않고 반올림 자체 만 수행하는 경우 필요에 따라 층을 int로 형변환 할 수 있습니다.

또 다른 이유는 double의 범위가 int의 범위보다 훨씬 크기 때문입니다. 모든 double을 int로 반올림하는 것은 불가능할 수도 있습니다.

+1

floor()는 0이 아닌 무한대로 반올림됩니다. http://www.cplusplus.com/reference/clibrary/cmath/floor.html –

+0

doh, 물론 맞습니다. 결정된. – jalf

5

다양한 숫자 조건을 처리하고 제어 된 방식으로 여러 가지 유형의 전환을 처리하려는 경우 Boost.NumericConversion을 확인해야합니다. 이 라이브러리는 (범위를 벗어난 것은, 반올림, 범위 등 같은) 여기

이 문서의 예입니다 이상한 경우를 처리 할 수 ​​있습니다 :

#include <cassert> 
#include <boost/numeric/conversion/converter.hpp> 

int main() { 

    typedef boost::numeric::converter<int,double> Double2Int ; 

    int x = Double2Int::convert(2.0); 
    assert (x == 2); 

    int y = Double2Int()(3.14); // As a function object. 
    assert (y == 3) ; // The default rounding is trunc. 

    try 
    { 
     double m = boost::numeric::bounds<double>::highest(); 
     int z = Double2Int::convert(m); // By default throws positive_overflow() 
    } 
    catch (boost::numeric::positive_overflow const&) 
    { 
    } 

    return 0; 
} 
2

표준 수학 라이브러리의 대부분은 사용이 복식하지만, float 버전도 제공합니다. double을 사용하지 않으려는 경우 std :: floorf()는 std :: floor()의 단 정밀도 버전입니다.

편집 : 이전 답변 일부를 삭제했습니다. 정수로 캐스팅 할 때 바닥이 중복되었다고 말했지만, 이것은 양수 부동 소수점에만 해당된다는 사실을 잊어 버렸습니다.

6

은 C++ 표준 말한다 (4.9.1)

"부동 소수점 형식의 r- 수치는 정수 형태의 r- 수치로 변환 할 수있는 변환 절단, 즉, 분수 부분은 폐기된다..

따라서 double을 int로 변환하는 경우 숫자는 int 범위 내에 있고 필요한 반올림은 0을 향하게됩니다. 다음은 int로 간단하게 수를 캐스팅 충분하다 :

(INT) ×;

+0

소수 부분의 잘림은 바닥이 아닙니다. 결과는 음수와 다릅니다. – Suma

+0

필자는이 경우를 "무한대로 반올림"하는 것과 구별하기 위해 "필요한 경우 반올림이 필요합니다."라고 분명히 기술했습니다. Floor는 -infinity로 반올림되며 자르기는 0으로 향하게됩니다. –

관련 문제