这个函数是用python编写的。我试图测量Python和C之间的性能。 流利的C能否帮助将此功能转换为C?
输入字符串
0T1M1L1BtT1L1BtT1TtT1B1T1H1E1I1PtT1B2Z1C1L1G1NtTtNtT2Z1M1T2ZtT2W1PtT1T1C1PtTzutT2Z1P1B2Z1L1G1N
解码后的输出
这是一个示例字符串&我们=测试
这是python中的函数:
def decode(encstr):
# Number of characters in string should be even
# If it's not - remove last character
if (len(encstr) % 2 != 0):
encstr = encstr[:-1] # length of string - 1
strlen = len(encstr)
i = 0
decrypted = []
while (i < strlen):
# get character at position i
cc = encstr[i];
# get integer representing the Unicode code point of the character
cch = ord(cc)
nch = ord(encstr[i + 1])
if cc == '0':
v = nch
elif cc == 'z':
v = cch - nch + 56
elif cc in ['1', '2', '3', '4', '5', '6', '7', '8', '9']:
v = (cch - 49) * 25 + 181 - nch
else:
v = cch - nch
if(v < 0):
v = (v % 256) + 256
if v > 255:
v = v % 256
# append the decrypted character
decrypted.append(chr(v))
i += 2
return ''.join(decrypted)
答案 0 :(得分:3)
为什么不使用已编写的扩展,而不是编写自己的C扩展来提高性能?我当然在谈论NumPy!
import numpy as np
def decode(encstr):
arr = np.array(encstr, 'c').view(np.uint8) # to ASCII codes
out = np.empty(len(encstr) / 2, np.uint8)
out[:] = arr[::2] - arr[1::2] # v = cch - nch, default case
mask = np.where(arr == ord('0'))[0] # cc == '0'
out[mask / 2] = arr[mask + 1] # v = nch
mask = np.where(arr == ord('z'))[0] # cc == 'z'
out[mask / 2] = arr[mask] - arr[mask + 1] + 56 # cch - nch + 56
mask = np.where(np.logical_and(arr >= ord('1'), arr <= ord('9')))[0] # cc in ['1'..'9']
out[mask / 2] = (arr[mask] - ord('1')) * 25 + 181 - arr[mask + 1] # (cch - ord('1')) * 25 + 181 - nch
return ''.join(out.view('c')) # back from ASCII codes
这缺少原始代码中的一两个功能(我确定你可以在真正需要的时候添加它们),但是对于给定的输入样本它可以正常工作。
哦,如果它不清楚这里发生了什么:我已经对算法进行了矢量化,认识到这些字符对都是独立的,所以NumPy可以用来执行条件运算一次遍历整个字符串,在Python本身没有迭代。
答案 1 :(得分:2)
天真,1对1翻译因为我懒惰而且无聊并且不想继续研究我应该做的事情(C99或更高版本):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
void decode( const char *encstr,
size_t decrypt_len,
char decrypt[ static decrypt_len ] )
{
assert( encstr );
size_t len = strlen( encstr );
//
// Create a local copy of the encrypted string, since we want to
// modify the input below
//
char lencstr[len + 1];
strcpy( lencstr, encstr );
if ( len % 2 )
lencstr[len - 1] = 0;
const char *cc = lencstr;
const char *nc = cc + 1;
while ( *cc )
{
int v;
if ( *cc == '0' )
v = *nc;
else if ( *cc == 'z' )
v = *cc - *nc + 56;
else if ( isdigit( *cc ) )
v = (*cc - 49) * 25 + 181 - *nc;
else
v = *cc - *nc;
if ( v < 0 )
v = ( v % 256 ) + 256;
else if ( v > 255 )
v = v % 256;
*decrypt++ = (char) v;
cc += 2;
nc += 2;
}
*decrypt = 0;
}
int main( void )
{
const char *enc = "0T1M1L1BtT1L1BtT1TtT1B1T1H1E1I1PtT1B2Z1C1L1G1NtTt"
"NtT2Z1M1T2ZtT2W1PtT1T1C1PtTzutT2Z1P1B2Z1L1G1N";
char dec[ strlen(enc) + 1 ];
printf( "Encrypted string: %s\n", enc );
decode( enc, sizeof dec, dec );
printf( "Decrypted string: %s\n", dec );
return 0;
}
构建和输出:
[fbgo448@n9dvap997]~/prototypes/decoder: !g gcc -o decoder -g -std=c99 -pedantic -Wall -Werror decoder.c [fbgo448@n9dvap997]~/prototypes/decoder: ./decoder Encrypted string: 0T1M1L1BtT1L1BtT1TtT1B1T1H1E1I1PtT1B2Z1C1L1G1NtTtNtT2Z1M1T2ZtT2W1PtT1T1C1PtTzutT2Z1P1B2Z1L1G1N Decrypted string: This is a sample string & that we are = testing