문제

긍정적 인 정수 번호에 대한 3 개의 기본 표현이 있습니다.

  1. 서명되지 않은 긴 변수 (예 : 서명되지 않은 긴 int numdec = 200).
  2. 문자열 변수에서 16 진수 (예 : 문자열 NumHex = "C8")
  3. 문자열 변수의 이진 (예 : 문자열 numbin = "11001000")

3 가지 표현 모두에서 가장 효율적인 방식으로 숫자를 변환 할 수 있기를 원합니다. 즉, 다음 6 가지 기능을 구현하려면 :

unsigned long int Binary2Dec(const string & Bin) {}
unsigned long int Hex2Dec(const string & Hex) {}
string Dec2Hex(unsigned long int Dec) {}
string Binary2Hex(const string & Bin) {}
string Dec2Binary(unsigned long int Dec) {}
string Hex2Binary(const string & Hex) {}

그들 각각에 가장 효율적인 접근법은 무엇입니까? C와 C ++를 사용할 수는 있지만 부스트 할 수는 없습니다.

편집 : "효율성"에 의해 시간 효율성 : 최단 실행 시간을 의미합니다.

도움이 되었습니까?

해결책

다른 사람들이 지적했듯이 나는 sscanf(), printf() 및/또는 strtoul(). 대부분의 응용 프로그램에 대해 충분히 빠르며 버그가 적을 가능성이 적습니다. 그러나 이러한 기능은 ASCII가 아닌 문자 세트를 처리해야하며 숫자가 모든 기반에 표시되어야하기 때문에 예상보다 더 일반적이라고 말할 것입니다. 일부 도메인의 경우 라이브러리 기능을 이길 수 있습니다.

따라서 먼저 측정하고 이러한 변환의 성능이 실제로 문제라면 :

1) 일부 애플리케이션 / 도메인에서 특정 숫자는 매우 자주 나타납니다 (예 : Zero, 100, 200, 19.95). 그러한 숫자를 if () 문으로 변환하기 위해 함수를 최적화하는 것이 합리적 일 수 있습니다. 일반 라이브러리 기능으로 돌아갑니다. 2) 가장 일반적인 100 숫자 인 경우 테이블 조회를 사용한 다음 라이브러리 기능으로 돌아갑니다. 대형 테이블은 캐시에 맞지 않을 수 있으며 공유 라이브러리에 대한 여러 간디가 필요할 수 있으므로 성능을 줄이지 않도록 조심스럽게 측정하십시오.

부스트 lexical_cast 기능을보고 싶을 수도 있지만, 내 경험상 후자는 좋은 오래된 C 함수와 비교할 수 있습니다.

힘든 많은 사람들은 반복해서 반복 할 가치가 있습니다. 문제가 있다는 증거가있을 때까지 이러한 변환을 최적화하지 마십시오. 최적화하는 경우 새 구현을 측정하여 더 빨리 확인하십시오. 그리고 버그를 소개하기 때문에 자신의 버전에 대한 단위 테스트가 많이 있는지 확인하십시오 .-(

다른 팁

나는 그냥 사용하는 것이 좋습니다 Sprintf 그리고 SSCANF.

또한 구현 방법에 관심이 있으시면 소스 코드 ~을 위한 GNU C 라이브러리 GLIBC.

이 루틴이 왜 그렇게 시간 효율적이어야합니까? 그런 종류의 주장은 항상 나를 궁금해합니다. strtol ()과 같은 명백한 변환 방법이 너무 느리거나 더 잘할 수 있다고 확신합니까? 시스템 기능은 일반적으로 매우 효율적입니다. 때때로 일반성과 오류 확인을 지원하는 데 속도가 느리지 만 오류로 무엇을 해야하는지 고려해야합니다. 만약 bin 인수는 '0'과 '1'이외의 캐릭터가 있습니다. 그렇다면 무엇입니까? 중단? 대규모 오류를 전파합니까?

"DEC"를 사용하여 내부 표현을 나타내는 이유는 무엇입니까? 12 월, 16 진수 및 빈은 문자열 표현을 참조하는 데 사용해야합니다. 소수점은 없습니다 unsigned long. 소수점으로 숫자를 보여주는 문자열을 다루고 있습니까? 그렇지 않다면, 당신은 여기 사람들을 혼란스럽게하고 더 많은 것을 혼동 할 것입니다.

이진과 16 진 텍스트 형식의 변환은 조회 테이블을 사용하여 빠르고 효율적으로 수행 할 수 있지만 소수점 텍스트 형식과 관련된 것은 더 복잡합니다.

그것은 당신이 최적화하는 것에 달려 있습니다. "효율적인"이란 무엇을 의미합니까? 전환이 빠르고, 메모리를 적고, 프로그래머 시간을 적게 사용하는 것이 중요합니까? wtfs 코드를 읽는 다른 프로그래머로부터?

가독성과 구현의 용이성을 위해 최소한 두 가지를 구현해야합니다. Dec2Hex() 그리고 Dec2Binary() 전화로 strotul (). 그것은 그것들을 하나의 라이너로 만듭니다. 이는 단어의 상기 해석 중 적어도 일부에 매우 효율적입니다.

숙제 문제와 매우 흡사하지만 도대체 ...

짧은 대답은 긴 INT에서 문자열로 변환하는 것입니다. 두 개의 조회 테이블을 사용합니다. 각 테이블에는 256 개의 항목이 있어야합니다. 하나의 맵 a 바이트에서 16 진 문자열 : 0-> "00", 1-> "01"등. 다른 하나는 바이트 a 바이트 a 비트 문자열 : 0 -> "00000000", 1-> "00000001".

그런 다음 긴 int의 각 바이트에 대해 올바른 문자열을 찾아서 연결하면됩니다.

문자열에서 길이로 다시 변환하려면 각 문자의 숫자 값에 적절한 전력을 16 또는 2의 적절한 전력으로 곱하여 16 진 문자열과 비트 문자열을 소수 숫자로 다시 변환하고 결과를 요약 할 수 있습니다.

편집 : 바이너리 검색을 수행하여 올바른 문자열을 찾아서 동일한 조회 테이블을 뒤로 변환 할 수도 있습니다. 이것은 문자열의 로그 (256) = 8 비교가 필요합니다. 불행히도 나는 문자열 비교가 정수를 곱하고 추가하는 것보다 훨씬 빠른지 여부를 분석 할 시간이 없습니다.

현악기의베이스 n에서 서명되지 않은 긴 길로 변환하는 순간의 절반에 대해 생각해 봅시다. 여기서 n은 2의 전력입니다 (이진의 경우 2, 16 진의 경우 16베이스).

입력이 제정신이라면이 작업은 비교, 서브랙트, 시프트 및 숫자 당 또는 숫자에 지나지 않습니다. 당신의 입력이 제정신이 아니라면, 그것이 못 생기는 곳입니다. 전환 초고속을하는 것은 어렵지 않습니다. 모든 상황에서 잘하는 것은 도전입니다.

그러니 입력이 제정신이라고 가정 해 봅시다. 그러면 전환의 핵심이 다음과 같습니다.

unsigned long PowerOfTwoFromString(char *input, int shift)
{
    unsigned long val = 0;
    char upperLimit = 'a' + (1 << shift)
    while (*input) {
        char c = tolower(*input++);
        unsigned long digit = (c > 'a' && c < upperLimit) ? c - 'a' + 10 : c - '0';
        val = (val << shift) | digit;
    }
    return val;
 }

 #define UlongFromBinaryString(str) PowerOfTwoFromString(str, 1)
 #define UlongFromHexString(str) PowerOfTwoFromString(str, 4)

그것이 얼마나 쉬운 지 보십니까? 그리고 비-산 입력에서는 실패 할 것입니다. 대부분의 작업은 성능이 아니라 입력을 제정신으로 만들 것입니다.

이제이 코드는 두 가지 변화의 힘을 활용합니다. 베이스 4,베이스 8,베이스 32 등으로 확장하기 쉽습니다. 이를 위해서는 수학이 바뀌어야합니다. 당신은 얻습니다

val = (val * base) + digit

이 작업 세트에서 개념적으로 동일합니다. 베이스에 의한 곱셈은 이동과 동일합니다. 그래서 나는 대신에 완전히 일반적인 일상을 사용할 가능성이 높습니다. 입력을 소독하면서 코드를 소독합니다. 그리고 그 시점에서 Strtoul은 아마도 최선의 방법 일 것입니다. 다음은 다음과 같습니다 버전 Strtoul의. 거의 모든 작업은 가장자리 조건을 처리하는 것입니다. 이는 에너지가 집중되어야하는 곳, 즉 정확하고 탄력적 인 코드에 대한 단서를 제공해야합니다. 비트 시프트를 사용하기위한 절약은 잘못된 입력에 충돌하지 않고 Say의 절약에 비해 최소화됩니다.

매크로를 사용하여 형식을 입력으로 사용하는 것이 어떻습니까? 당신이 적어도 C에 있다면.

#define TO_STRING( string, format, data) \
sprintf( string, "##format##", data)
// Int
TO_STRING(buf,%d,i);
// Hex ( Two char representation )
TO_STRING(buf,%02x,i);
// Binary
TO_STRING(buf,%b,i);

또는 sprintf를 직접 사용할 수 있습니다. 또는 여러 개의 매크로를 가질 수 있습니다.

#define INT_STRING( buf, data) \
sprintf( buf, "%d", data)
#define HEX_STRING( buf, data) \
sprintf( buf, "%x", data)
#define BIN_TO_STRING( buf, data) \
sprintf( buf, "%b", data)

BIN_TO_STRING( loc_buf, my_bin );
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top