将无符号短整数转换为char *(即将25转换为'25')是一种有效,便携的方式。
我想避免使用诸如获取(std :: string)字符串之类的内容。在这种情况下,性能很重要,因为这种转换需要快速而且经常发生。
我正在研究诸如使用sprintf之类的事情,但我想探索任何想法。
答案 0 :(得分:6)
首先,做正确,然后快速完成 - 只有在你可以确定某段代码不具备性能时才进行优化。
snprintf()
进入缓冲区会做你想要的。它是最快的解决方案吗?一点也不。但它是最简单的,只需将代码置于工作状态即可。从那里,如果您发现那些对snprintf()
的调用过于费力以至于需要进行优化,那么然后只有寻求更快的解决方案。
答案 1 :(得分:2)
一串字符串
array[25] = "25";
array[26] = "26";
array[255] = "255";
可能?你可以编写一个很容易为你生成表源代码的小程序,然后在你的项目中使用这个文件。
编辑:我不明白你的意思,你不想涉及ge字符串。
答案 2 :(得分:1)
我想说至少尝试一下sprintf,因为你把它标记为C ++,试试StringStream,然后实际对它们进行分析。在许多情况下,编译器足够聪明,可以构建非常好用的东西。只有当你知道它会成为一个瓶颈时,你才需要找到更快的方法。
答案 3 :(得分:1)
试试这个:
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;
}
答案 4 :(得分:1)
我在这里攻击了各种功能的测试,这就是我想出来的:
write_ushort:7.81 s
uShortToStr:8.16 s
转换:6.71 s
use_sprintf:49.66 s
(Write_ushort是我的版本,我试图尽可能清楚地写,而不是微优化,格式化为给定的字符缓冲区; 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时,整个范围再次完成2,999次。
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 };
};