2009-12-10 2 views
1

데이터베이스 엔진에 대한 숫자 형식 변환 함수 집합을 쓰고 있는데 큰 정수 부동 소수점 값을 다음과 같이 변환하는 동작이 걱정됩니다. 더 정밀도가 높은 정수 유형.int -> float -> int 왕복 변환에 반올림 사용

예를 들어 32 비트 정수를 32 비트 단정도 부동 소수점으로 변환합니다. float의 23 비트 유효 부분은 약 7 자리의 정밀도를 산출하므로 약 7 자리 이상의 int를 변환하면 정밀도가 떨어지게됩니다. 당신이 int로 다시 같은 float를 변환 할 때, 당신은 하위 자리에서의 이진 표현의 유물로 끝날 :

#include <iostream> 
#include <iomanip> 

using namespace std; 

int main() 
{ 
    int a = 2147483000; 
    cout << a << endl; 
    float f = (float)a; 
    cout << setprecision(10) << f << endl; 
    int b = (int)f; 
    cout << b << endl; 

    return 0; 
} 

이 인쇄 :

2147483000 
2147483008 
2147483008 

후행 008입니다 따라서 float의 정밀도를 넘어서서 int에 유지하는 것이 바람직하지 않은 것처럼 보입니다. 데이터베이스 응용 프로그램에서 사용자는 주로 10 진수 표현에 관심을 갖고 후미에 0은 중요하지 않은 숫자를 나타내는 데 사용됩니다.

제 질문은 다음과 같습니다 : float -> int (또는 double -> long long) 변환에서 십진수 유효 숫자 반올림을 수행하는 잘 알려진 기존 시스템이 있습니까? 그래서?

(참고 : 일부 시스템에는 IEEE 754-2008과 같이 10 진수 부동 소수점 유형이 있지만, 주류 하드웨어 지원이 없으며 C/C++에 내장되어 있지 않습니다. 도로를 지원하려면 직관적으로 이진수를 처리해야합니다.)

+0

이러한 상황은 "왜 왕복 변환이?"묻는 붉은 깃발을 보냅니다 이것은 값이 float가 아닌 정수로 데이터베이스에 저장되어야 함을 의미합니다. 대수 표현을 단순화하는 것과 같습니다. –

+0

좋은 질문입니다. 분명히 왕복 변환을 계획하지 않으며 데이터베이스 엔진 자체에서 이러한 일이 발생하지는 않습니다. 그러나이 데이터베이스는 조밀하게 패킹 된 메모리 내 데이터 용으로 설계되었으므로 가능한 가장 작은 유형을 사용해야합니다.필자는 이진 부동 소수점을 더 높은 정밀도의 int 또는 10 진수 부동 소수점으로 변환 할 때 실제보다 훨씬 더 정밀하다고 생각하는 사용자 (자신의 SQL과 유사한 쿼리를 제출할 수 있음)를 원하지 않습니다. –

답변

1

std::numeric_limits<float>::digits10에는 float에 대해 6 자리의 정확한 숫자 만 있다고합니다.

언어, 프로세서 및 데이터 배포에 대한 효율적인 알고리즘을 calculate-the-decimal-length-of-an-integer (또는 here)으로 선택하십시오. 그런 다음 digits10이 말한 자릿수를 빼서자를 자릿수를 얻습니다. 이것을 지수로 사용하여 10의 거듭 제곱을 찾아 계수로 사용하십시오. 기타

하나의 관심사 : 부동 소수점을 10 진수로 변환하고 이런 종류의 반올림 또는 잘라 내기를 수행한다고 가정 해 봅시다. 그런 다음 "조정 된"십진수를 부동 소수점 형으로 변환 한 후 동일한 반올림/잘라 내기 방식으로 소수점으로 다시 변환하십시오. 동일한 10 진수 값을 얻습니까? 바라건대 네.

은 당신이 찾고 있지만, 흥미로운 독서 할 수있다 정말로되지 않습니다 : A Proposal to add a max significant decimal digits value to the C++ Standard Library Numeric limits

+0

고마워! numeric_limits에서 digits10의 존재를 간과하고 그 목적을 위해 (significand의 비트를 기반으로 한) 내 자신의 특성 템플릿을 도입했습니다. 당신의 접근 방식은 기본적으로 내가 함께하기로 결정한 것이므로, 독립적 인 검증을하는 것이 좋습니다. 그 제안은 참으로 흥미 롭습니다. 이 문제에 대한 추가적인 시각을 제공합니다. –

0

이진 (1111111111111111111110110000000) 또는 16 진수 (0b0x7FFFFD80)로 쓰면 당연히 2147483008의 후미에 0이 있습니다. 가장 올바른 "할 일"은 해당 양식에서 중요하지 않은 자릿수를 추적하는 것입니다.

또는 부동 소수점에 약 7 자리 숫자가 포함되어 있기 때문에 float에서 변환 한 후 int에서 (이상적으로 반올림하여) 처음 7 자리의 중요 숫자 뒤에 모든 숫자를 0으로 만들 수 있습니다.

+0

뛰어난 명료화 포인트. 그러나, 나는 이진 또는 16 진수가이 데이터베이스에 저장된 데이터를 표시하는 데 사용되기를 정말로 기대하지 않습니다. 내 질문은 정말로 두 번째 단락을 구현하는 지혜/선례와 가장 효율적인 방법으로 내려갑니다. –

관련 문제