【问题标题】:How to do unsigned 32 bit arithmetic in Perl?如何在 Perl 中进行无符号 32 位运算?
【发布时间】:2021-09-23 17:17:28
【问题描述】:

我想在 Perl 中实现以下 C 程序:

#include <stdio.h>
#include <stdint.h>

uint32_t xorshift32 ()
{
  static uint32_t y = 2463534242;
  y ^= y << 13;
  y ^= y >> 17;
  y ^= y << 5;
  return y;
}

int main (int argc, char *argv[])
{
  int n = 10;
  while (n-- > 0)
    printf ("%u\n", xorshift32());
}

输出是:

723471715
2497366906
2064144800
2008045182
3532304609
374114282
1350636274
691148861
746858951
2653896249

这是我失败的尝试:

{
  package Xorshift;
  use strict;
  use warnings;
  use integer;

  sub new
  {
    my $class = shift;
    bless { y => 2463534242 } => $class
  }

  sub rand ()
  {
    my $y = $_[0]->{y};
    $y ^= $y << 13;
    $y ^= $y >> 17;
    $y ^= $y << 5;
    $_[0]->{y} = $y;
    return $y;
  }
}

my $xor = Xorshift->new;

my $n = 10;
while ($n-- > 0) {
  print $xor->rand(), "\n";
}

输出是这样的:

660888219700579
3396719463693796860
-1120433007023638100
2588568168682748299
1469630995924843144
-8422345229424035168
1449080611344244726
-4722527344582589597
8061824971057606814
-3113862584906767882

问题:

  1. Perl 使用 64 位算法。
  2. 整数是有符号的。

如何改用 32 位无符号算术?

【问题讨论】:

  • Re "Perl 使用 64 位算法。",取决于构建
  • Re "整数是有符号的。",编号perl -E"$x = 2**62; $x &lt;&lt;= 1; say $x" 给出9223372036854775808。删除,use integer;,你就不会有这个问题了

标签: perl 32-bit integer-overflow unsigned-integer


【解决方案1】:

如果你想模拟 32 位操作的结果,你可以简单地应用一个掩码:

{
  package Xorshift;
  use strict;
  use warnings;
  use integer;

  sub new
  {
    my $class = shift;
    bless { y => 2463534242 } => $class
  }
  
  sub to32{
    return ($_[0] & 0xFFFFFFFF);
  }

  sub rand ()
  {
    my $y = $_[0]->{y};
    $y ^= to32($y << 13);
    $y ^= to32($y >> 17);
    $y ^= to32($y << 5);
    $_[0]->{y} = $y;
    return $y;
  }
}

my $xor = Xorshift->new;

my $n = 10;
while ($n-- > 0) {
  print $xor->rand(), "\n";
}

【讨论】:

  • 这似乎适用于 64 位系统。但是掩盖左移就足够了吗?如果没有额外的函数调用,它的运行速度会提高一倍。
  • @ceving,子调用很慢。只需内联它。
  • 左移和右移都用to32 屏蔽。正如@ikegami 所说,您当然可以内联掩码。为了与你的 C 代码保持一致,你还应该在包中屏蔽 $y 的原始定义,但除非你设置的数字太大,否则没有必要。
猜你喜欢
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2013-05-03
  • 2011-01-17
  • 2019-02-21
  • 2012-04-03
  • 2019-10-31
  • 2016-05-31
相关资源
最近更新 更多