字符串转整数,谁来下挑战极限速度!
需求
字符分析无需太复杂,只要能识别负数就行。遇到非数字则结束。使用单线程计算。
"12345" => 12345
"-1357" => -1357
"135.7" => 135
"abcde" => 0
评分
相对C语言自带的atoi的性能倍数。比率值越大越好。
我先提供一个。(本机测试,比C自带的 atoi 快3.8倍)
- C/C++ code
int atoi_v1(const char* s){ int sign = 0; if(s[0] == '-') { sign = 1; s++; } __asm { mov ecx, s ; pos = s xor eax, eax ; 总数 xor edx, edx ; 个位数 ;------------------------------ ; 二进制 Ascii ; 0011-0000 '0' ; 0011-0001 '1' ; ... ; 0011-1001 '9' ;------------------------------next_char: mov dl, byte ptr [ecx] ; dl = *pos cmp dl, '0' ; 判断字符是否为数字 jb done cmp dl, '9' ja done and dl, 00001111b ; 低4位,对应十进制数字 shl eax, 1 ; sum = sum * 10 lea eax, [eax * 4 + eax] add eax, edx ; sum = sum + dig inc ecx ; pos++ jmp next_chardone: cmp sign, 1 ; 判断是否有负号 jne no_sign neg eax ; sum = -sumno_sign: }}
测试代码:
- C/C++ code
int main(int argc, char* argv[]){ #define N 20000000 // 自己的 atoi int t1 = ::GetTickCount(); for(int i = 0; i < N; i++) { atoi_v1("123456789"); atoi_v1("-123456789"); } t1 = ::GetTickCount() - t1; // C运行时的 atoi int t2 = ::GetTickCount(); for(int i = 0; i < N; i++) { atoi("123456789"); atoi("-123456789"); } t2 = ::GetTickCount() - t2; // 性能倍数 cout << "rate:" << (float)t2 / (float)t1 << endl; getchar(); return 0;}
虽然是用汇编写的,不过写的比较简单,所以性能提升并不十分明显。有兴趣的来优化下看看,能提升多少。
[解决办法]
优化得差不多了。
两点意见:
1. 还是要检测一下空指针,只需要加一条指令:
mov ecx, s ; pos = s
xor eax, eax ; 总数
jecxz no_sign_done
基本不损失性能。
2. 代码展开,消去inc ecx,大概还能再提高20%左右。在我的能力之内,这基本上就是极限了。:)