Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Perl function for negative integers using the 2's complement in hex?

Reply
Thread Tools

Perl function for negative integers using the 2's complement in hex?

 
 
stylechief
Guest
Posts: n/a
 
      04-08-2005
I cannot seem to find a Perl function that will return the 2's
complement of a negative integer represented in hex.
For example:
ffbe8e should return -16754, not 16760462

hex() works fine for positive integers but not here
pack/unpack don't seem to want to produce anything negative (just 0)

I imagine that there is a 'brute force' method, but it seems that there
should be an eloquent function that speaks in 2's complement . . . .

Thanks,
Liam

 
Reply With Quote
 
 
 
 
Joe Smith
Guest
Posts: n/a
 
      04-08-2005
stylechief wrote:
> I cannot seem to find a Perl function that will return the 2's
> complement of a negative integer represented in hex.
> For example:
> ffbe8e should return -16754, not 16760462


You have to remember that 32-bit integers are represented by
eight hex digits, not six.

linux% perl -le 'printf "%d %d\n",0xffbe8e,0xffffbe8e'
16760462 -16754

If you have a 24-bit number you will need to sign-extend the
most significant bit in order to produce a 32-bit number.

linux% cat temp
$bits_24 = hex("ffbe8e");
$bits_32 = $bits_24 | (($bits_24 & 0x800000) ? 0xff000000 : 0);
printf "%d %.0f\n", $bits_32, $bits_32;

linux% perl temp
-16754 4294950542
 
Reply With Quote
 
 
 
 
stylechief
Guest
Posts: n/a
 
      04-08-2005

Thanks for the help, guys. It is a 24 bit number I'm working with.

 
Reply With Quote
 
stylechief
Guest
Posts: n/a
 
      04-11-2005
That works like a charm when one can explicitly pass a hex number like
the above example. However, for whatever reason, when one attempts to
read from a binary file and use unpack() to deliver the hex numbers,
one gets:
Argument "ffbe8e" isn't numeric in pack at E:\Test\bif.plx line 5.

code:
open (BINARYFILE, "<000332") || die "Cant open: $!\n";
while(read(BINARYFILE, $data, 3)){
$data= unpack 'H*',$data;
print unpack 'i',pack 'i',$data;
print "\n";
}
close (BINARYFILE) || die"Cant close: $!\n";

It *is* unpacking to a 24 bit hex number, but fails to see this number
as numeric. It gets "stringified" somehow.

 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      04-12-2005
stylechief <(E-Mail Removed)> wrote:

> That works like a charm



What does?


> when one can explicitly pass a hex number like
> the above example.



What example above?


Please compose followups the normal way and quote some context.


--
Tad McClellan SGML consulting
http://www.velocityreviews.com/forums/(E-Mail Removed) Perl programming
Fort Worth, Texas
 
Reply With Quote
 
Joe Smith
Guest
Posts: n/a
 
      04-12-2005
stylechief wrote:
> That works like a charm when one can explicitly pass a hex number like
> the above example. However, for whatever reason, when one attempts to
> read from a binary file and use unpack() to deliver the hex numbers,
> one gets:
> Argument "ffbe8e" isn't numeric in pack at E:\Test\bif.plx line 5.
>
> code:
> open (BINARYFILE, "<000332") || die "Cant open: $!\n";
> while(read(BINARYFILE, $data, 3)){
> $data= unpack 'H*',$data;
> print unpack 'i',pack 'i',$data;
> print "\n";
> }
> close (BINARYFILE) || die"Cant close: $!\n";
>
> It *is* unpacking to a 24 bit hex number,



No, it is unpacking to a six-character string of hexadecimal digits.
The phrase "24 bit hex number" is meaningless, what you've got is
a 24-bit number expressed as a string of hexadecimal digits.

> but fails to see this number as numeric. It gets "stringified" somehow.


Using 'H' with unpack() returns a string, not a number.
The string of hexadecimal digits needs to go through the hex() function
in order to be numeric.

$hexdata = unpack 'H*',$data;
$integer = hex $hexdata;
print unpack 'i', pack 'i',$integer;

or

read(BINARYFILE, $three_bytes, 3);
$four_bytes = '\x00' . $three_bytes;
$integer = unpack 'i',$four_bytes;

or

$sign_extend = ($three_bytes & "\x80\x00\x00") ? "\xff" : "\x00";
$four_bytes = $sign_extend . $three_bytes;

(Obviously, little-endian machines and big-endian ones need to
handle those last two differently.)

-Joe
 
Reply With Quote
 
stylechief
Guest
Posts: n/a
 
      04-12-2005
Thanks to all for your time and consideration. The solution that I was
seeking:

open (BINFILE, "<000332") || die "Cant open: $!\n";
while(read(BINFILE, $data, 3)){

$data=hex(unpack 'H*',$data);
if ($data & 0x800000) {$data |= 0xff000000};
printf "%d \n", $data;

}
close (BINFILE) || die "Cant close: $!\n";

Unless there is yet a more efficient method . . . .

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
2's complement vs. 1's complement vs. ... Roberto Waltman C Programming 4 06-13-2011 11:26 PM
1's complement and 2's complement sarathy C++ 22 08-02-2006 05:53 PM
1's complement and 2's complement sarathy C Programming 20 08-02-2006 05:53 PM
Negative setup and Negative hold prem_eda VHDL 5 10-11-2004 12:14 PM
sign magnitude, ones complement, two's complement Mantorok Redgormor C Programming 8 10-07-2003 11:52 PM



Advertisments