最佳base-10仅ITOA()函数
Optimal Base-10 only itoa() function?
在20多年的编程中,我使用了一次以外的10个以外的基础,所以当我在另一个环境中找到我值得信赖的msvc的_itoa()在另一个环境中缺少了一个,我开始写一个这只能做10,并放置目标缓冲区参数,指向函数返回的存储,左侧,而不是在右侧,就像C标准库中的所有字符串函数一样。我相信此代码也是线程安全。
是否有更快的方法来执行此操作?
我也要询问正确性,但我相信随附的测试代码证明了它有效,即使对于long_min的特定情况,也就是(-1 * long_max)-1,这会导致代码中的故障直到我改变了战术,指出了标志,然后将签名的INT复制到未签名的INT中。然后,我在未签名的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 %sn", t, _i32toa(buff, t));
printf("nString from integer %i is %sn", -0, _i32toa(buff, -0));
printf("nString from integer %i is %sn", -1, _i32toa(buff, -1));
printf("nString from integer %i is %sn", 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中的不合时宜的_itoa()和10-15x的2-4x。
该方法有些新颖,取决于知道完整的字符串所需的缓冲区大小 - 问题分配了其自己的字符串缓冲区的功能,buff []求解,使其同时使其线程安全。
知道缓冲区的末端在哪里允许从背面到正面写下字符串的字符,从而解决了反向顺序问题。调用函数不需要以任何方式准备 *rtn,因为将memcpy()ed的工作字符串已经终止。
TVMIA的反馈。缺乏良好的_atoi()函数是一个足够持久的问题,值得一个好的解决方案。让我们做一个。
ps:在我的i7 Hazwell盒子上运行MSVS C 64位,具有完整的优化,从long_min到long_max平均每次转换为116个时钟,用于往返行程,只有28个时钟对于_itoa()。如果与Ben Voigt的代码进行比较,则每秒超过725兆字节。我想我赢了本!
您可以通过直接写入呼叫者的内存区域来消除memcpy
。
您应该让呼叫者通过缓冲区的大小。
另一个瓶颈是分裂,但我看不出如何解决。
编辑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;
}
摆脱自动char阵列并使它们的尺寸使它们可以检查溢出。
#define I32TOA( buff, val ) _i32toa( (buff), sizeof(buff), (val) )
char * _i32toa(char *const rtn, size_t size, int32_t i) {
if (NULL == rtn) return NULL;
uint32_t ut, ui;
char minus_sign=0;
char *p = rtn + size-1;
*p-- = 0; // nul-terminate buffer
assert( p >= rtn );
if (i < 0) {
minus_sign = '-';
ui = (uint32_t)((int)-1 * (int)i);
} else {
ui = i;
}
while (ui > 9) {
ut = ui;
ui /= 10;
*p-- = (ut - (ui * 10)) + 48;
assert( p >= rtn );
}
*p = ui + 48;
if ('-' == minus_sign) {
*--p = minus_sign;
assert( p >= rtn );
}
return p;
}
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 如何将长整型传递给 itoa 函数?
- 最佳base-10仅ITOA()函数
- 'itoa':函数不带1个参数&'c':未声明的标识符
- 模板函数中的Itoa