为何在Numba中使用uint64类型时无法执行按位与(&)操作?
Numba中uint64类型popcount函数的类型错误问题
最小可复现示例(MWE)
import numba as nb @nb.njit(nb.uint64(nb.uint64)) def popcount(x): b=0 while(x > 0): x &= x - 1 b+=1 return b print(popcount(43))
运行报错信息
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend) No implementation of function Function(<built-in function iand>) found for signature: >>> iand(float64, float64) There are 8 candidate implementations: - Of which 4 did not match due to: Overload of function 'iand': File: <numerous>: Line N/A. With argument(s): '(float64, float64)': No match. - Of which 2 did not match due to: Operator Overload in function 'iand': File: unknown: Line unknown. With argument(s): '(float64, float64)': No match for registered cases: * (bool, bool) -> bool * (int64, int64) -> int64 * (int64, uint64) -> int64 * (uint64, int64) -> int64 * (uint64, uint64) -> uint64 - Of which 2 did not match due to: Overload in function 'gen_operator_impl.<locals>._ol_set_operator': File: numba/cpython/setobj.py: Line 1508. With argument(s): '(float64, float64)': Rejected as the implementation raised a specific error: TypingError: All arguments must be Sets, got (float64, float64) raised from /home/user/python/mypython3.10/lib/python3.10/site-packages/numba/cpython/setobj.py:108 During: typing of intrinsic-call at /home/user/python/popcount.py (7) File "popcount.py", line 7: def popcount(x): <source elided> while(x > 0): x &= x - 1 ^
补充说明
即使显式传入nb.uint64类型参数,仍会触发相同错误:
print(popcount(nb.uint64(43)))
问题原因
核心问题是隐式类型转换:
- 函数参数
x被声明为uint64,但循环条件中的0是Python默认的int64类型。 - 由于
uint64的取值范围(0到18446744073709551615)超出了int64的范围(-9223372036854775808到9223372036854775807),Numba为了执行x > 0的比较,会将x隐式转换为float64类型。 - 一旦
x的类型变为float64,后续的x &= x - 1操作就变成了对浮点数执行按位与操作,而Numba并未实现浮点数的按位与重载,因此触发TypingError。
解决方法
修改循环条件中的常量为uint64类型,避免隐式转换:
import numba as nb @nb.njit(nb.uint64(nb.uint64)) def popcount(x): b = nb.uint64(0) # 同时将b初始化为uint64,匹配返回类型 while(x > nb.uint64(0)): x &= x - 1 b += nb.uint64(1) return b print(popcount(43)) # 输出:3
或者使用Numba的常量装饰器明确类型:
import numba as nb @nb.njit(nb.uint64(nb.uint64)) def popcount(x): b = nb.uint64(0) zero = nb.const(0, nb.uint64) one = nb.const(1, nb.uint64) while(x > zero): x &= x - one b += one return b
内容的提问来源于stack exchange,提问作者Simd
相关产品推荐
相关产品推荐

