Функция C для Python (разные результаты)
Я пытаюсь портировать этот фрагмент кода на Python из C. Выводы разные, хотя это тот же код.
Это версия кода C, которая работает:
int main(void)
{
uint8_t pac[] = {0x033,0x55,0x22,0x65,0x76};
uint8_t len = 5;
uint8_t chan = 0x64;
btLeWhiten(pac, len, chan);
for(int i = 0;i<=len;i++)
{
printf("Whiten %02d \r\n",pac[i]);
}
while(1)
{
}
return 0;
}
void btLeWhiten(uint8_t* data, uint8_t len, uint8_t whitenCoeff)
{
uint8_t m;
while(len--){
for(m = 1; m; m <<= 1){
if(whitenCoeff & 0x80){
whitenCoeff ^= 0x11;
(*data) ^= m;
}
whitenCoeff <<= 1;
}
data++;
}
}
В настоящее время у меня есть в Python:
def whiten(data, len, whitenCoeff):
idx = len
while(idx > 0):
m = 0x01
for i in range(0,8):
if(whitenCoeff & 0x80):
whitenCoeff ^= 0x11
data[len - idx -1 ] ^= m
whitenCoeff <<= 1
m <<= 0x01
idx = idx - 1
pac = [0x33,0x55,0x22,0x65,0x76]
len = 5
chan = 0x64
def main():
whiten(pac,5,chan)
print pac
if __name__=="__main__":
main()
Проблема, которую я вижу, состоит в том, что whitenCoeff всегда остается 8 бит в фрагменте C, но он становится больше, чем 8 бит в Python на каждом проходе цикла.
5 ответов
В C вы пишете данные от 0 до len-1, но в Python вы пишете данные от -1 до len-2. Удалите -1 из этой строки:
data[len - idx -1 ] ^= m
как это
data[len - idx] ^= m
Вы также должны поместить эту строку вне if:
whitenCoeff <<= 1
У вас есть еще несколько проблем.
whitenCoeff <<= 1;
находится за пределамиif
блок в вашем коде C, но это внутриif
блок в вашем коде Python.data[len - idx -1 ] ^= m
не был правильно переведен, он работает в обратном направлении от кода C.
Этот код производит тот же вывод, что и ваш код на C:
def whiten(data, whitenCoeff):
for index in range(len(data)):
for i in range(8):
if (whitenCoeff & 0x80):
whitenCoeff ^= 0x11
data[index] ^= (1 << i)
whitenCoeff = (whitenCoeff << 1) & 0xff
return data
if __name__=="__main__":
print whiten([0x33,0x55,0x22,0x65,0x76], 0x64)
whitenCoeff <<= 1
через некоторое время C становится 0, потому что это 8-битные данные.
В python такого ограничения нет, поэтому вы должны написать:
whitenCoeff = (whitenCoeff<<1) & 0xFF
маскировать старшие биты.
(не забудьте проверить замечание vz0 о границе массива)
плюс была проблема с отступом.
переписанный код, который дает тот же результат:
def whiten(data, whitenCoeff):
idx = len(data)
while(idx > 0):
m = 0x01
for i in range(0,8):
if(whitenCoeff & 0x80):
whitenCoeff ^= 0x11
data[-idx] ^= m
whitenCoeff = (whitenCoeff<<1) & 0xFF
m <<= 0x01
idx = idx - 1
pac = [0x33,0x55,0x22,0x65,0x76]
chan = 0x64
def main():
whiten(pac,chan)
print(pac)
if __name__=="__main__":
main()
Немного не по теме: обратите внимание, что версия C уже имеет проблемы:
for(int i = 0;i<=len;i++)
должно быть
for(int i = 0;i<len;i++)
Я решил это, добавив код Python с 0xFF. Это удерживает переменную от превышения 8 бит.
Ваш код в C
не работает должным образом, поскольку отображает еще одно значение, чем доступно в pac
, Исправление для этого должно привести к отображению 5 значений вместо 6 значений. Чтобы скопировать логику из C
к Python
в попытке дублировать результаты было написано следующее:
#! /usr/bin/env python3
def main():
pac = bytearray(b'\x33\x55\x22\x65\x76')
chan = 0x64
bt_le_whiten(pac, chan)
print('\n'.join(map('Whiten {:02}'.format, pac)))
def bt_le_whiten(data, whiten_coeff):
for offset in range(len(data)):
m = 1
while m & 0xFF:
if whiten_coeff & 0x80:
whiten_coeff ^= 0x11
data[offset] ^= m
whiten_coeff <<= 1
whiten_coeff &= 0xFF
m <<= 1
if __name__ == '__main__':
main()
Для имитации 8-битных целых чисел без знака, фрагмент & 0xFF
используется в нескольких местах, чтобы обрезать числа до нужного размера. bytearray
тип данных используется для хранения pac
так как это представляется наиболее подходящим способом хранения в этом случае. Код все еще нуждается в документации, чтобы правильно понять это.