Я собрал здесь тест различных функций, и вот что я придумал:
write_ushort: 7,81 с
uShortToStr: 8,16 с
преобразование: 6,71 с
use_sprintf: 49,66 с
(Write_ushort - моя версия, которую я попытался написать как можно более четко, а не микрооптимизировать, для форматирования в заданный символьный буфер; use_sprintf - это очевидный sprintf (buf, "% d).", х) и ничего больше; два других взяты из других ответов здесь.)
Это довольно удивительная разница между ними, не так ли?Кто бы мог подумать, что использовать 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 преобразовывал весь возможный диапазон беззнаковых шорт , а затем снова делал весь диапазон еще 2999 раз примерно0,25 мкс на конверсию в среднем на моем ~ 5-летнем ноутбуке.
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 };
};