给定一个(无符号)整数,将它转换为包含十进制表示的字符串的最常用方法是什么?
这种天真的做法是重复除以10,直到你达到零。我不喜欢这种方法,因为它
我想到了以下方法将整数转换为十进制基数。这是一个好主意吗?如何在printf
等函数的常见实现中完成此操作?
#include <stdint.h>
const static uint64_t i64_tab[20] = {
1u,
10u,
100u,
1000u,
10000u,
100000u, /* 10^ 5 */
1000000u,
10000000u,
100000000u,
1000000000u,
10000000000u, /* 10^10 */
100000000000u,
1000000000000u,
10000000000000u,
100000000000000u,
1000000000000000u, /* 10^15 */
10000000000000000u,
100000000000000000u,
1000000000000000000u,
10000000000000000000u /* 10^19 */
};
void uint64_to_string(char *out, uint64_t in) {
int i;
uint64_t tenpow;
char accum;
for (i = 19;i > 0;i--) {
if (in >= i64_tab[i]) break;
}
do {
tenpow = i64_tab[i];
accum = '0';
while (in >= tenpow) {
in -= tenpow;
accum++;
}
*out++ = accum;
} while (i --> 0);
*out = '\0';
}
const static uint32_t i32_tab[10] = {
1u,
10u,
100u,
1000u,
10000u,
100000u, /* 10^ 5 */
1000000u,
10000000u,
100000000u,
1000000000u, /* 10^9 */
};
void uint32_to_string(char *out, uint32_t in) {
int i;
uint32_t tenpow;
char accum;
for (i = 9;i > 0;i--)
if (in >= i32_tab[i]) break;
do {
tenpow = i32_tab[i];
accum = '0';
while (in >= tenpow) {
in -= tenpow;
accum++;
}
*out++ = accum;
} while (i --> 0);
*out = '\0';
}
答案 0 :(得分:2)
我认为通过常数进行整数除法与进行乘法一样快,因为编译器将整数除法优化为常数除数的整数乘法。这是大多数优化编译器执行的重型数学技巧。
答案 1 :(得分:2)
除最简单(例如8位)微控制器之外的所有微控制器的最快方法是使用除法,但通过一次生成几个数字来减少除法数。
您会在我的问题here的答案中找到非常高度优化的代码。在C中使用它应该是一个简单的编辑,以消除std::string
- 实际转换中没有使用C ++功能。核心是
while(val>=100)
{
int pos = val % 100;
val /= 100;
*(short*)(c-1)=*(short*)(digit_pairs+2*pos); // or use memcpy
c-=2;
}
while(val>0)
{
*c--='0' + (val % 10);
val /= 10;
}
我还为8位微处理器提供了一个优化的无分区代码,类似于问题代码中显示的思想,但没有循环。它最终得到了很多像这样的代码:
if (val >= 80) {
ch |= '8';
val -= 80;
}
else if (val >= 40) {
ch |= '4';
val -= 40;
}
if (val >= 20) {
ch |= '2';
val -= 20;
}
if (val >= 10) {
ch |= '1';
val -= 10;
}
答案 2 :(得分:1)
通常最快的方法是索引到一个足够大的字符串指针数组。一个数组查找,一个指针解除引用。尽管如此......内存使用量很大......这就是工程权衡的本质。速度有多快?
答案 3 :(得分:1)
printf的MS版本以“天真”的方式(在根据可选标志设置一堆变量之后):
while (precision-- > 0 || number != 0) {
digit = (int)(number % radix) + '0';
number /= radix; /* reduce number */
if (digit > '9') {
/* a hex digit, make it a letter */
digit += hexadd;
}
*text.sz-- = (char)digit; /* store the digit */
}