Cython не может привести отрицательное значение к беззнаковому длинному

Я пытаюсь преобразовать большое отрицательное значение внутри класса Cython в переменную типа uint64_t. Но я продолжаю получать эту ошибку:

OverflowError: невозможно преобразовать отрицательное значение в беззнаковое длинное

cdef uint64_t temp2 = <uint64_t>(temp - bitReversal(current_pos))

Число, которое я получаю от temp - bitReversal(current_pos), - -1152831344652320768, и если я жестко запрограммировал его, он работает. На данный момент я создаю действительно уродливый хак, преобразующий отрицательное число в соответствующее беззнаковое, но, как и ожидалось, он очень медленный.


person Alan Höng    schedule 18.09.2014    source источник
comment
Изменить <uint64_t> на (uint64_t)? (И примите переполнение.)   -  person user2864740    schedule 19.09.2014
comment
Могу я спросить почему вы пытаетесь преобразовать отрицательное число в беззнаковое значение?   -  person Cory Kramer    schedule 19.09.2014
comment
Я рассчитываю маску движения ладьи для игры, похожей на шахматы .(uint64_t) недопустимый синтаксис для cython   -  person Alan Höng    schedule 19.09.2014
comment
Два числа, которые вы вычитаете, положительны? Затем просто преобразуйте их оба в uint64_t, а затем положитесь на тот факт, что беззнаковые целые числа C имеют гарантированное поведение переполнения. (Выполнение арифметики со знаком и последующее приведение к беззнаковому не гарантировано; оно основывается на том факте, что подписанные числа вашей платформы являются 2s-дополнительными, реализованы очевидным образом, и что ваш компилятор не делает предположений что они не будут переполняться - и эта последняя часть не всегда может быть верной в современных системах, даже если первые две части верны.)   -  person abarnert    schedule 19.09.2014


Ответы (1)


Спасибо, abarnert, что сработало. Эта строка заставила его работать: cdef uint64_t temp2 = <uint64_t>(temp - <uint64_t>bitReversal(current_pos))

Но это действительно странно, потому что обе переменные имеют тип uint64_t.

def bitReversal(uint64_t x):
    x = (((x & 0xaaaaaaaaaaaaaaaa) >> 1) | ((x & 0x5555555555555555) << 1))
    x = (((x & 0xcccccccccccccccc) >> 2) | ((x & 0x3333333333333333) << 2))
    x = (((x & 0xf0f0f0f0f0f0f0f0) >> 4) | ((x & 0x0f0f0f0f0f0f0f0f) << 4))
    x = (((x & 0xff00ff00ff00ff00) >> 8) | ((x & 0x00ff00ff00ff00ff) << 8))
    x = (((x & 0xffff0000ffff0000) >> 16) | ((x & 0x0000ffff0000ffff) << 16))
    cdef uint64_t result = <uint64_t>((x >> 32) | (x << 32))
    return result
person Alan Höng    schedule 18.09.2014
comment
Обе переменные не могли быть uint64_t, иначе вычитание не дало бы отрицательного результата. Может быть, вам где-то не хватает cdef, поэтому одна из переменных была скопирована в Python int где-то по пути? В этом случае я считаю, что Cython вычтет их, преобразовав значение C в Python и попросив Python вычесть (что, помимо этой проблемы переполнения, вероятно, также является той проблемой производительности, которую вы хотите избежать). - person abarnert; 19.09.2014
comment
Используйте cython -a myfile.pyx и ищите желтый. Если ваша математика желтая, значит, у вас все в порядке. - person Veedrac; 20.09.2014