读书人

字符串转整数哪位高手来下挑战极限速

发布时间: 2013-03-26 09:54:33 作者: rapoo

字符串转整数,谁来下挑战极限速度!
本帖最后由 zjcqoo 于 2012-09-19 16:02:07 编辑 需求
  字符分析无需太复杂,只要能识别负数就行。遇到非数字则结束。使用单线程计算。
  "12345" => 12345
  "-1357" => -1357
  "135.7" => 135
  "abcde" => 0
评分
  相对C语言自带的atoi的性能倍数。比率值越大越好。
  
  
  我先提供一个。(本机测试,比C自带的 atoi 快3.8倍)

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_char
done:
cmp sign, 1 ; 判断是否有负号
jne no_sign
neg eax ; sum = -sum
no_sign:
}
}


  


  测试代码:

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%左右。在我的能力之内,这基本上就是极限了。:)

读书人网 >软件架构设计

热点推荐