unsigned short를 char *로 변환 (즉, 25를 '25'로 변환)하는 것은 효율적이고 이식 가능한 방법은 무엇입니까?부호없는 short를 char *로 효율적으로 변환 *
나는 (std :: string) 문자열을 가져 오는 것과 같은 것을 피하고 싶습니다. 이 변환은 신속하고 자주 발생해야하기 때문에 성능이 중요합니다.
저는 sprintf를 사용하는 것과 같은 것을 찾고 있었지만 어떤 아이디어라도 탐색기에 넣고 싶습니다.
unsigned short를 char *로 변환 (즉, 25를 '25'로 변환)하는 것은 효율적이고 이식 가능한 방법은 무엇입니까?부호없는 short를 char *로 효율적으로 변환 *
나는 (std :: string) 문자열을 가져 오는 것과 같은 것을 피하고 싶습니다. 이 변환은 신속하고 자주 발생해야하기 때문에 성능이 중요합니다.
저는 sprintf를 사용하는 것과 같은 것을 찾고 있었지만 어떤 아이디어라도 탐색기에 넣고 싶습니다.
먼저 해보고 빨리 해보십시오. 특정 코드가 성능이 좋지 않다는 것을 확실히 볼 수있는 경우에만 최적화하십시오.
snprintf()
버퍼로 원하는 것을 할 수 있습니다. 가능한 가장 빠른 솔루션입니까? 전혀. 그러나 가장 간단한 방법 중 하나는 코드를 작동 상태로 만드는 것입니다. 여기에서 snprintf()
에 대한 호출이 매우 힘들어서 최적화해야하는 경우, 다음으로 만 빠른 솔루션을 찾으십시오.
적어도 sprintf를 시도해보고 C++로 태그를 지정 했으므로 StringStream을 시도하고 실제로 프로필을 작성하십시오. 많은 경우 컴파일러는 꽤 잘 작동하는 것을 만들기에 충분히 똑똑합니다. 병목 현상이 될 것이라는 것을 알고있을 때만 실제로 더 빠른 방법을 찾아야합니다.
문자열의 배열 등 아마
array[25] = "25";
array[26] = "26";
array[255] = "255";
인가? 아주 쉽게 테이블 소스 코드를 생성하는 작은 프로그램을 작성한 다음 프로젝트에서이 파일을 사용할 수 있습니다.
편집 : 나는 당신이 의미하는 것을 얻지 못한다.
문자열로 생각합니다. 그들은 "std :: string"을 의미합니다. 나는 그것도 혼란스러워했다. – gravitron
이 시도 :
int convert(unsigned short val, char* dest)
{
int i = 0;
if (val > 10000)
{
dest[i++] = (val/10000) | 0x30;
val %= 10000;
}
if (val > 1000)
{
dest[i++] = (val/1000) | 0x30;
val %= 1000;
}
if (val > 100)
{
dest[i++] = (val/100) | 0x30;
val %= 100;
}
if (val > 10)
{
dest[i++] = (val/10) | 0x30;
val %= 10;
}
dest[i++] = (val) | 0x30;
dest[i] = 0;
return i;
}
아마도 마지막'dest [i] = '\ 0';'? –
@Tony, oops - 잘 잡으세요! – Nim
:
write_ushort : 7.81의
uShortToStr : 8.16의
변환 : 6.71s
use_sprintf : 49.66s
(Write_ushort는 제 버전으로, p 마이크로 최적화보다는 ossible을 사용하여 주어진 문자 버퍼로 형식화합니다. use_sprintf는 명백한 sprintf (buf, "% d", x)이며 다른 것은 없습니다. 나머지 두 개는 다른 답변에서 가져온 것입니다.)
이것은 꽤 놀라운 차이입니다. sprintf를 거의 모든 차별화 된 순서로 사용하는 것을 누가 생각할 것입니까? 오, 예, 테스트 된 각 함수를 몇 번 반복 했습니까?
// Taken directly from my hacked up test, but should be clear.
// Compiled with gcc 4.4.3 and -O2. This test is interesting, but not authoritative.
int main() {
using namespace std;
char buf[100];
#define G2(NAME,STMT) \
{ \
clock_t begin = clock(); \
for (int count = 0; count < 3000; ++count) { \
for (unsigned x = 0; x <= USHRT_MAX; ++x) { \
NAME(x, buf, sizeof buf); \
} \
} \
clock_t end = clock(); \
STMT \
}
#define G(NAME) G2(NAME,) G2(NAME,cout << #NAME ": " << double(end - begin)/CLOCKS_PER_SEC << " s\n";)
G(write_ushort)
G(uShortToStr)
G(convert)
G(use_sprintf)
#undef G
#undef G2
return 0;
}
sprintf를 내 ~ 5 살짜리 노트북, 평균 전환 당 약 0.25 μs의 다시 2999 번 이상을 전체 범위를 한 다음, 부호 없음 short의 전체 가능한 범위를 변환.
Sprintf는 휴대용입니다. 그것은 또한 귀하의 요구 사항에 대해 충분히 효율적입니까?
내 버전 :
// Returns number of non-null bytes written, or would be written.
// If ret is null, does not write anything; otherwise retlen is the length of
// ret, and must include space for the number plus a terminating null.
int write_ushort(unsigned short x, char *ret, int retlen) {
assert(!ret || retlen >= 1);
char s[uint_width_10<USHRT_MAX>::value]; // easy implementation agnosticism
char *n = s;
if (x == 0) {
*n++ = '0';
}
else while (x != 0) {
*n++ = '0' + x % 10;
x /= 10;
}
int const digits = n - s;
if (ret) {
// not needed by checking retlen and only writing to available space
//assert(retlen >= digits + 1);
while (--retlen && n != s) {
*ret++ = *--n;
}
*ret = '\0';
}
return digits;
}
컴파일 시간 그것이 내가 무엇을 사용 때문에 TMP 기능은 아무것도 새로운,하지만 완전한 예제를 포함하지 않습니다 로그 :
template<unsigned N>
struct uint_width_10_nonzero {
enum { value = uint_width_10_nonzero<N/10>::value + 1 };
};
template<>
struct uint_width_10_nonzero<0> {
enum { value = 0 };
};
template<unsigned N>
struct uint_width_10 {
enum { value = uint_width_10_nonzero<N>::value };
};
template<>
struct uint_width_10<0> {
enum { value = 1 };
};
실제로 그 차이는 놀랍지 않습니다. sprintf는 다양한 형식 지정자를 가질 수 있습니다 ... 알고리즘에서 고려해야 할 사람이있을 수 있습니다. sprintf 나 심지어는 좀 더 느린 짐승 같은 것을 보지 못했습니다. 대부분의 경우 최적화할만한 가치가없는 프로필에서 실행 시간의 상당 부분을 차지하는 boost :: format과 같습니다. –
작은 천사가이 게시물에 풍자를 사용하지 말자고 누군가가 그것에 대해 의견을 말하게되었습니다. 나는 듣지 않았다. 이 기능은 거의 2 억 번 (USHRT_MAX, 여기 65,535, * 3,000) 실행되기 때문에 큰 차이가있는 것처럼 보입니다. @ ÖöTiib : 프로파일 작성자를 사용하지 않고 OP를 보여준 결론을 다시 한 번 나타내 보았습니다. 프로파일 작성을 위해 OP 코드에 액세스 할 수 없기 때문에 다시 말 했습니다. –
예,하지만 솔루션을 제공했습니다. 왜냐하면 ... 누가 알기 때문입니다. 진짜 문제가 보이지 않으면 냉소적이어서는 안됩니다. 어떤 이유로 텍스트 기반 인터페이스와 프로토콜이 인기를 얻었고 두 모듈이 sprintf를 사용하여 수백만 개의 서명되지 않은 단락을 서로에게 말하면 병목이 될 수 있습니다. 나는 물론 그러한 경우에 바이너리 인터페이스/프로토콜로 전환하는 것을 선호 할 것이지만 재검토 인터페이스는 다른 이유로 인해 비싸거나 문제가 될 수있다. –
이 사용 해봤' sprintf' /'snprintf'? 코드를 프로파일 링하고 이것이 성능 핫스팟이라고 결정 했습니까? –
아래에 링크 된 기사 하단의 표는 구현의 효율성과 최적성에 관한 한 stdlib 구현이 어디에 위치 하는지를 명확하게 보여줍니다. http://www.codeproject.com/KB/recipes/Tokenizer.aspx –