【问题标题】:Python ctypes.c_int to Perl XS (or non-XS) conversion (Javascript signed 32-bit bitwise shift operator conversion)Python ctypes.c_int 到 Perl XS(或非 XS)的转换(Javascript 有符号的 32 位位移运算符转换)
【发布时间】:2019-02-21 07:12:20
【问题描述】:

背景

我们需要将 Javascript 哈希算法转换为 Perl 代码。因此,我们需要将 Javascript 的移位运算符 > 和 >>> 转换为 Perl。到目前为止,我们已经有了进行转换的算法,但是由于 Javascript 的按位移位运算符对 32 位整数进行操作,因此我们还需要在 Perl 中进行模拟。

Python 解决方案

根据这篇文章https://stackoverflow.com/a/41610348,我们了解到我们可以在 Python 中使用 ctypes 来做到这一点。例如,将整数左移 x 位:

import ctypes
print (ctypes.c_int(integer << x ^ 0).value)

Perl 问题

我的理解是,我们需要使用 XS 来做到这一点。我的问题是是否有人有一个快速的解决方案来实施它。我们不知道 XS。我们可以开始学习它,但从我的印象来看,学习曲线非常高,可能需要一段时间才能掌握它。当然,如果存在非 XS 解决方案,那将是理想的。任何解决方案或提示将不胜感激。

解决方法

由于我们已经有了 Python 解决方案,我们可以在 Python 中实现这个模块,然后从 Perl 中调用它。性能并不是真正的问题,因此这种“hack”是可以接受的,尽管有些不可取。换句话说,我们更愿意只在 Perl 中维护整个程序(由几个模块组成)。

【问题讨论】:

  • 将结果截断为 32 位还不够吗?如use constant { I32 =&gt; 0xffff_ffff }; ... ($x &lt;&lt; $n) &amp; I32?
  • 你能给我们看看 JavaScript 哈希码吗?
  • @melpomene 感谢您的建议,但这不起作用。我们已经尝试了一些类似的实现。较大的整数在移位后可能会溢出 32 位边界,因此简单地截断结果并不总是给出正确的答案。在 SO 上的 Python 解决方案中已经给出了其他几个类似的解决方案,但从测试来看,唯一每次都有效的解决方案是使用 ctypes.c_int
  • 你的团队中有人写 C 吗?然后你可以使用metacpan.org/pod/C::Blocksmetacpan.org/pod/distribution/Inline-C/lib/Inline/C.pod
  • @DiabJerius Inline::C 看起来会起作用。它还附带一本食谱:https://metacpan.org/pod/distribution/Inline-C/lib/Inline/C/Cookbook.pod 感谢您的建议。我稍后会试一试。

标签: javascript python perl bitwise-operators


【解决方案1】:
sub lshr32 { ( $_[0] & 0xFFFFFFFF ) >> $_[1] }                           # >>> in JS
sub lshl32 { ( $_[0] << $_[1] ) & 0xFFFFFFFF }

sub ashr32 { ( $_[0] - ( $_[0] % ( 1 << $_[1] ) ) ) / ( 1 << $_[1] ) }   # >> in JS
sub ashl32 { unpack "l", pack "l", $_[0] * ( 1 << $_[1] ) }              # << in JS

将负数传递给逻辑移位是没有意义的,除非该数字不是真正的数字而是位的集合。鉴于您正在移植散列算法,这很有可能。这也意味着您通过与 JavaScript 紧密匹配来为自己创建许多额外的工作,因为您正在重新创建用于解决 JavaScript 限制的技巧,而这些限制在 Perl 中不存在。使用 32 位无符号值应该更简单,&lt;&lt; 使用 &amp; 0xFFFFFFFF 截断,&gt;&gt; 使用 &amp; 0xFFFFFFFF 截断。

【讨论】:

  • 将负数传递给逻辑移位是没有意义的,但&gt;&gt;&gt; 的行为似乎是为负数定义的。您只需要转换输入,我已将其添加到我的 lshr32
  • 你的改变只是让 sub 更复杂而不改变输出
  • int 的大小必须容纳 -32767..32767。它可以小于 32 位。它可以大于 32 位。
  • 什么情况?正数和负数?它已经处理了这两个问题。同样,您的添加实际上没有任何效果。
  • 我们终于明白你的解释了。因为您在#&gt;&gt;&gt; in JS 评论下将lshr32lshl32 混为一谈,所以我们认为它们需要结合使用。我们最初在负数上进行测试,从lshr32得到了很好的结果,所以我们错误地认为lshl32是一个正数实现。我们缺乏技术知识使我们感到困惑,并且很遗憾地使您感到沮丧。很抱歉让你觉得这个问题很乏味。再次感谢您宝贵的帮助和时间。
猜你喜欢
  • 2019-10-31
  • 2019-07-26
  • 2019-05-23
  • 2013-05-03
  • 1970-01-01
  • 2012-03-04
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多