Как сделать расчет языка Си в Python - PullRequest
2 голосов
/ 16 июня 2011

Я хочу провести симуляцию вычисления языка Си в Python. Например, unsigned short, float одинарной точности ...

ushort(0xffff) + 1 -> 0
0.1f * 0.1f -> ...

Есть ли какая-нибудь библиотека для этого на Python?

Я могу использовать ctypes для создания беззнакового короткого одиночного плавающего числа, но они не могу выполнить математическую операцию:

a = c_uint16(0xffff)
b = c_uint16(0x01)
a+b -> TypeError

Или я могу использовать numpy:

>>> np.uint16(0xffff) + np.uint16(0x01)
Warning: overflow encountered in ushort_scalars
0

но это очень медленно по сравнению с обычными вычислениями Python:

>>> timeit.timeit("a+b", "import numpy as np;a=np.uint16(0xfffe);b=np.uint16(0x01)")
0.35577465681618037
>>> timeit.timeit("0xfffe+0x01")
0.022638104432360251
>>> timeit.timeit("np.uint16(0xfffe) + np.uint16(0x01)", "import numpy as np")
5.904765399236851  

Edit:

>>> timeit.timeit("a+b", "a=0xfffe;b=0x01")
0.040062221014295574  

Ответы [ 2 ]

6 голосов
/ 16 июня 2011

При компиляции 0xfffe+0x01 это будет складываться в константу 65535.Вы не определяете, сколько времени занимает добавление - вы просто измеряете время загрузки константы:

>>> dis.dis(compile("0xfffe+0x01", "", "eval"))
  1           0 LOAD_CONST               2 (65535)
              3 RETURN_VALUE        

Добавление скаляров NumPy тем не менее медленнее, чем добавление встроенных целых чисел, но оно выигралолучше, чем в чистом Python.Попробуйте использовать Cython - это позволит вам объявлять типы и выполнять вычисления на C-скорости.Или попробуйте векторизовать ваш код в NumPy (то есть, если скорость действительно имеет значение).

1 голос
/ 16 июня 2011

Вы можете создать функцию для каждой операции, используя модуль % с 2**sizeof (в вашем случае 2 ** 16 или 65536)

def add(a, b, mod=2**16):
    return (a+b) % mod

def sub(a, b, mod=2**16):
    return (a-b) % mod

и любые другие необходимые вам функции.

>>> add(0xffff, 1)
0
>>> sub(10, 20)
65526

Обратите внимание, что это будет работать только для неподписанных типов. Для подписанных вы можете использовать половину значения, используемого для мода (то есть 2 ** 15), и вам придется проверить результат перед применением по модулю

...