2010-09-07 3 views
1

Я пытаюсь преобразовать AD maxpwdAge (64-разрядное целое число) в несколько дней.Функция Perl для отрицательных целых чисел с использованием дополнения 2

According to Microsoft:

Использует Get метод интерфейса Iads, чтобы получить значение домена maxPwdAge атрибута (строка 5).

Обратите внимание, что мы используем ключевое слово Set в VBScript для инициализации переменной с именем objMaxPwdAge-переменной, используемой для хранения значения, возвращаемого Get. Почему это?

Когда вы извлекаете 64-битное большое целое число, ADSI не возвращает одно гигантское скалярное значение. Вместо этого ADSI автоматически возвращает объект IADsLargeInteger. Для вычисления значения большого целого используются свойства IADsLargeInteger интерфейса HighPart и LowPart. Как вы, возможно, догадались, HighPart получает 32 разряда высокого порядка, а LowPart получает младший бит 32 бит. Вы используете следующую формулу для преобразования HighPart и LowPart в значение большого целого.

Существующий код в 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?

ответ

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"; 
+0

ya .. он будет, но как сгенерировать высокую часть и низкую часть (для ex: значение -37108517437440) – Tree

+0

Я думал, что у вас были высокие и низкие 32-битные части и вы хотели построить исходное 64-битное значение , Что у тебя есть? –

+0

У меня 64-битное целое целое значение: -37108517437440 – Tree

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, вам нужно будет учитывать все проблемы точности.

Смежные вопросы