使用2的补码的负整数的Perl函数

时间:2010-09-07 12:48:02

标签: perl active-directory ldap

我正在尝试将AD maxpwdAge(64位整数)转换为若干天。

According to Microsoft

  

使用IADs接口的Get方法检索域maxPwdAge属性的值(第5行)。

     

请注意,我们在VBScript中使用Set关键字来初始化名为objMaxPwdAge的变量 - 用于存储Get返回的值的变量。那是为什么?

     

当您获取64位大整数时,ADSI不会返回一个巨大的标量值。相反,ADSI会自动返回IADsLargeInteger个对象。您可以使用IADsLargeInteger接口的HighPartLowPart属性来计算大整数的值。您可能已经猜到,HighPart获得高位32位,LowPart获得低位32位。您可以使用以下公式将HighPartLowPart转换为大整数的值。

来自同一页面的VBScript中的现有代码:

Const ONE_HUNDRED_NANOSECOND = .000000100   ' .000000100 is equal to 10^-7
Const SECONDS_IN_DAY = 86400

Set objDomain = GetObject("LDAP://DC=fabrikam,DC=com")     ' LINE 4
Set objMaxPwdAge = objDomain.Get("maxPwdAge")              ' LINE 5

If objMaxPwdAge.LowPart = 0 Then
  WScript.Echo "The Maximum Password Age is set to 0 in the " & _
               "domain. Therefore, the password does not expire."
  WScript.Quit
Else
  dblMaxPwdNano = Abs(objMaxPwdAge.HighPart * 2^32 + objMaxPwdAge.LowPart)
  dblMaxPwdSecs = dblMaxPwdNano * ONE_HUNDRED_NANOSECOND   ' LINE 13
  dblMaxPwdDays = Int(dblMaxPwdSecs / SECONDS_IN_DAY)      ' LINE 14
  WScript.Echo "Maximum password age: " & dblMaxPwdDays & " days"
End If

我如何在Perl中执行此操作?

2 个答案:

答案 0 :(得分:1)

Endianness可能会出现这种情况,但您可能会说

#!/usr/bin/perl

use strict;
use warnings;

my $num = -37_108_517_437_440;

my $binary = sprintf "%064b", $num;

my ($high, $low) = $binary =~ /(.{32})(.{32})/;

$high = oct "0b$high";
$low  = oct "0b$low";

my $together = unpack "q", pack "LL", $low, $high;

print "num $num, low $low, high $high, together $together\n";

答案 1 :(得分:0)

我错过了什么吗?据我所知,你的问题与2的补码没什么关系。据我所知,你需要/想做的就是

use Math::BigInt;

use constant MAXPWDAGE_UNIT_PER_SEC => (
      1000 # milliseconds
    * 1000 # microseconds
    * 10   # 100 nanoseconds
);

use constant SECS_PER_DAY => (
      24 # hours
    * 60 # minutes
    * 60 # seconds
);

my $maxpwdage_full = ( Math::BigInt->new( $maxpwdage_highpart ) << 32 ) + $maxpwdage_lowpart;

my $days = $maxpwdage_full / MAXPWDAGE_UNIT_PER_SEC / SECS_PER_DAY;

请注意,我故意使用2个独立的常量,并按顺序除以它们,因为这会使除数小于32位整数的范围。如果你想用另一种方式编写它并希望它在32位perls上正常工作,你必须记住所有的精度问题。