【问题标题】:Cython can not cast negative value to unsigned longCython 不能将负值转换为 unsigned long
【发布时间】:2025-11-30 22:50:01
【问题描述】:

我正在尝试将 Cython 类中的一个很大的负值转换为 uint64_t 类型变量。但我不断收到此错误:

溢出错误:无法将负值转换为无符号长

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

我从temp - bitReversal(current_pos) 得到的号码是 -1152831344652320768,如果我对其进行硬编码,它就可以工作。现在,我构建了一个非常丑陋的 hack,将负数转换为相应的无符号数,但正如预期的那样非常慢。

【问题讨论】:

  • &lt;uint64_t&gt; 更改为(uint64_t)? (并接受溢出。)
  • 请问为什么你试图将负数转换为无符号值?
  • 我正在为类似国际象棋的游戏计算车的移动掩码。(uint64_t) 不是 cython 的有效语法
  • 你减去的两个数字都是正数吗?然后只需将它们都转换为uint64_t,然后依靠 C 无符号整数保证溢出行为这一事实。 (进行有符号算术然后强制转换为无符号是保证的;它依赖于这样一个事实,即您平台的有符号数是 2 秒补码,以明显的方式实现,并且您的编译器不会做出假设它们不会溢出——最后一部分在现代系统上可能并不总是正确的,即使前两部分是这样。)

标签: python c casting cython uint64


【解决方案1】:

感谢 abarnert 的工作。 这条线使它工作: cdef uint64_t temp2 = &lt;uint64_t&gt;(temp - &lt;uint64_t&gt;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

【讨论】:

  • 两个变量都不能是uint64_t,否则减法不会是负数。您是否会在某处遗漏cdef,因此其中一个变量在途中被复制到Python int?在这种情况下,我相信 Cython 会通过将 C 值转换为 Python 并要求 Python 减去它们来减去它们(除了这个溢出问题之外,这很可能也是你想要避免的性能问题)。
  • 使用cython -a myfile.pyx 并寻找黄色。如果你的数学是黄色的,那么 abarnert 就赚钱了。
最近更新 更多