gpt4 book ai didi

c++ - 最佳 Base-10 仅 itoa() 函数?

转载 作者:搜寻专家 更新时间:2023-10-31 01:06:06 24 4
gpt4 key购买 nike

关闭。这个问题是 opinion-based 。它目前不接受答案。












想改善这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答。

7年前关闭。




Improve this question




在 20 多年的 C 编程中,我曾经使用过 10 以外的基数,所以当我发现我可信赖的 MSVC 的 _itoa() 在另一个环境中丢失时,我开始编写一个只执行基数 10 的程序,并放置目标缓冲区参数,指向函数返回的存储,在左边,而不是在右边,就像 C 标准库中的所有字符串函数一样。我相信这段代码也是线程安全的。

有没有更快的方法来做到这一点?

我也想询问正确性,但我相信包含的测试代码证明它有效,即使对于 LONG_MIN 的特殊情况,即 (-1 * LONG_MAX) -1,这导致代码失败,直到我改变策略,记下符号,然后将有符号整数复制到无符号整数。然后,我在 unsigned int 中完成了函数中的所有核心工作——它也能在 75% 的时间内愉快地运行。

char * _i32toa(char *const rtn, int32_t i)    {
if (NULL == rtn) return NULL;

// declare local buffer, and write to it back-to-front
char buff[12];
uint32_t ut, ui;
char minus_sign=0;
char *p = buff + sizeof(buff)-1;
*p-- = 0; // nul-terminate buffer

// deal with negative numbers while using an unsigned integer
if (i < 0) {
minus_sign = '-';
ui = (uint32_t)((int)-1 * (int)i);
} else {
ui = i;
}

// core code here...
while (ui > 9) {
ut = ui;
ui /= 10;
*p-- = (ut - (ui * 10)) + '0';
}
*p = ui + '0';

if ('-' == minus_sign) *--p = minus_sign;

// knowing how much storage we needed, copy chars from buff to rtn...
memcpy(rtn, p, sizeof(buff)-(p - buff));

return rtn;
}

// ------------------------------------------------------------------------------------------------
#define LOOP_KNT (SHRT_MAX * 1024)
// ------------------------------------------------------------------------------------------------
int main(void) {
time_t start = clock();

int32_t t = 123456, i;
char *buff = (char *)malloc(256);

for (i = (SHRT_MIN *1024); i < LOOP_KNT; i++) {
_i32toa(buff, i);
}
printf("\nElapsed time was %f milliseconds", (double)clock() - (double)(start));

start = clock();
for (i = (SHRT_MIN * 1024); i < LOOP_KNT; i++) {
_itoa(i, buff, 10);
}
printf("\nElapsed time was %f milliseconds", (double)clock() - (double)(start));

start = clock();
for (i = (SHRT_MIN * 1024); i < LOOP_KNT; i++) {
___itoa(i, buff, 10);
}
printf("\nElapsed time was %f milliseconds", (double)clock() - (double)(start));

printf("\nString from integer %i is %s\n", t, _i32toa(buff, t));
printf("\nString from integer %i is %s\n", -0, _i32toa(buff, -0));
printf("\nString from integer %i is %s\n", -1, _i32toa(buff, -1));
printf("\nString from integer %i is %s\n", LONG_MIN, _i32toa(buff, LONG_MIN));

start = clock();
for (int i = LONG_MIN; i < LONG_MAX; i++) {
if (i != atoi(_i32toa(buff, (int32_t)i))) {
printf("\nError for %i", i);
}
if (!i) printf("\nAt zero");
}
printf("\nElapsed time was %f milliseconds", (double)clock() - (double)(start));

getchar();
return 0;
}

性能是 Visual Studio 2013 中非 C 标准 _itoa() 的 2-4 倍,是 sprintf() 的 10-15 倍。

该方法有些新颖,并且取决于了解完整字符串所需的缓冲区大小 - 分配自己的字符串缓冲区的函数 buff[] 解决了这个问题,同时使其成为线程安全的。

知道缓冲区的末尾在哪里可以让字符串的字符从后到前写入,解决了逆序问题。调用函数不需要以任何方式准备 *rtn,因为将 memcpy() 转换为 *ptr 的工作字符串已经以空值结尾。

TVMIA 为您提供反馈。缺乏一个好的 _atoi() 函数是一个足够持久的问题,值得一个好的解决方案。让我们做一个。

PS: 在我的 i7 Hazwell 机器上运行 MSVS C++ 64 位并进行了全面优化,从 LONG_MIN 到 LONG_MAX 的完整循环平均每次转换需要 116 个时钟,而 _itoa() 只有 28 个时钟。如果与 Ben Voigt 的代码相比,每秒超过 725 兆字节的字符串。我想我赢了本!

最佳答案

您可以消除 memcpy通过直接写入调用者的内存区域。
您应该让调用者传递缓冲区的大小。

另一个瓶颈是 split ,但我不知道如何解决这个问题。

编辑 1:正确初始化缓冲区指针

char * _i32toa(char *const rtn, unsigned int buff_size, int32_t i)  
{
if (NULL == rtn) return NULL;

uint32_t ut, ui;
char minus_sign=0;
char *p = rtn + buff_size - 1;
// As before, without memcpy.
return rtn;
}

关于c++ - 最佳 Base-10 仅 itoa() 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21501815/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com