Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re^4: Split any number into string of 8-bit hex values (=1 byte)

by drsweety (Novice)
on Aug 30, 2021 at 19:25 UTC ( [id://11136246]=note: print w/replies, xml ) Need Help??


in reply to Re^3: Split any number into string of 8-bit hex values (=1 byte)
in thread Split any number into string of 8-bit hex values (=1 byte)

Yes please :-) If I'd convert anything from a quad and then remove unnecessary leading zeros so that I'd end up with 1, 2, 4 or 8 bytes I'm thinking that this should work. What does the regex look like?
  • Comment on Re^4: Split any number into string of 8-bit hex values (=1 byte)

Replies are listed 'Best First'.
Re^5: Split any number into string of 8-bit hex values (=1 byte)
by tybalt89 (Monsignor) on Aug 30, 2021 at 19:54 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11136191 use warnings; for my $n (0, 2, 20, 200, 2000, 20000, 200000) { my @bytes = reverse sprintf('%016X', $n) =~ s/^0{8}(0{4}(00)?)?//r = +~ /../g; print "$n => @bytes\n"; }

    Outputs:

    0 => 00 2 => 02 20 => 14 200 => C8 2000 => D0 07 20000 => 20 4E 200000 => 40 0D 03 00
      Well.... I'm not sure how your regex works BUT it works great for unsigned numbers :-)
      #!/usr/bin/perl use strict; use warnings; sub number2hexString { return my $output .= join ' ', map { join ' ', sprintf('%016X' +, $_) =~ s/^0{8}(0{4}(00)?)?//r =~ /../g } @_; } print number2hexString(2,20,200,2000,20000,200000)."\n";
      It doesn't completely solve my problem as it does not work with unsigned signed numbers

      UPDATE: sorry, I was confused, obviously the last sentence should read ... does not work with signed numbers

        Further to tybalt89's comment:

        ... your regex works ... works great for unsigned numbers ...
        […]
        ... it does not work with unsigned numbers ...

        I assume you mean signed numbers in the second case; if so, please supply representative test cases: just what output do you expect for -255, -256, -65535, -65536, etc.

        And I would strongly suggest concentrating on edge cases in your test cases, e.g. something like
            0, 1, 255, 256, 65535, 65536, 16777215, 16777216, 4294967295
        rather than
            2 20 200 2000 20000 200000

        Update: Also, are you aware that the sprintf 'x' format conversion is essentially unsigned:

        Win8 Strawberry 5.8.9.5 (32) Mon 08/30/2021 18:24:36 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings printf "%08x \n", -256; printf "%08x \n", 4294967040; ^Z ffffff00 ffffff00


        Give a man a fish:  <%-{-{-{-<

        Here's an sprintf approach that avoids regex fireworks:

        Win8 Strawberry 5.30.3.1 (64) Mon 08/30/2021 18:36:38 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings my @n_list = (0, 1, 255, 256, 65535, 65536, 16777215, 16777216, 429496 +7295,); sub n2hstr_2 { # compatible with perl version 5.8 return join ' ', map { my $w = $_ > 65535 ? 8 : $_ > 255 ? 4 : 2; unpack '(a2)*', sprintf '%0*x', $w, $_; } @_ ; } sub number2hexString { my $output; my $packTemplate; foreach my $i (@_) { if ($i > 65535) { $packTemplate = 'L>'; } elsif ($i > 255) { $packTemplate = 'S>'; } else { $packTemplate = 'C'; } $output .= join(' ', unpack('(H2)*', pack($packTemplat +e, $i))).' '; } return $output; } my $n_n2hstr = n2hstr_2 (@n_list); my $n_number2hexString = number2hexString(@n_list); print "@n_list \n"; print "'$n_n2hstr' \n"; print "'$n_number2hexString' \n"; ^Z 0 1 255 256 65535 65536 16777215 16777216 4294967295 '00 01 ff 01 00 ff ff 00 01 00 00 00 ff ff ff 01 00 00 00 ff ff ff ff' '00 01 ff 01 00 ff ff 00 01 00 00 00 ff ff ff 01 00 00 00 ff ff ff ff +'
        As you see, the outputs are the same — except that number2hexString() adds an extra space at the end of the output string! I don't attempt to handle negative numbers since I don't yet understand how they should be handled.


        Give a man a fish:  <%-{-{-{-<

        Assuming you meant "signed" for the second case, here's revised code with extended test cases.

        #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11136191 use warnings; my @test = map 2 * 10 ** $_, 0 .. 16; for my $n ( 0, @test, map -$_, @test ) { my @bytes = reverse sprintf('%016X', $n) =~ s/^0{8}(0{4}(00)?)?(?=[0-7])//r =~ s/^F{8}(F{4}(FF)?)?(?=[89A-F])//r =~ /../g; print "$n => @bytes\n"; }

        Outputs:

        0 => 00 2 => 02 20 => 14 200 => C8 00 2000 => D0 07 20000 => 20 4E 200000 => 40 0D 03 00 2000000 => 80 84 1E 00 20000000 => 00 2D 31 01 200000000 => 00 C2 EB 0B 2000000000 => 00 94 35 77 20000000000 => 00 C8 17 A8 04 00 00 00 200000000000 => 00 D0 ED 90 2E 00 00 00 2000000000000 => 00 20 4A A9 D1 01 00 00 20000000000000 => 00 40 E5 9C 30 12 00 00 200000000000000 => 00 80 F4 20 E6 B5 00 00 2000000000000000 => 00 00 8D 49 FD 1A 07 00 20000000000000000 => 00 00 82 DF E4 0D 47 00 -2 => FE -20 => EC -200 => 38 FF -2000 => 30 F8 -20000 => E0 B1 -200000 => C0 F2 FC FF -2000000 => 80 7B E1 FF -20000000 => 00 D3 CE FE -200000000 => 00 3E 14 F4 -2000000000 => 00 6C CA 88 -20000000000 => 00 38 E8 57 FB FF FF FF -200000000000 => 00 30 12 6F D1 FF FF FF -2000000000000 => 00 E0 B5 56 2E FE FF FF -20000000000000 => 00 C0 1A 63 CF ED FF FF -200000000000000 => 00 80 0B DF 19 4A FF FF -2000000000000000 => 00 00 73 B6 02 E5 F8 FF -20000000000000000 => 00 00 7E 20 1B F2 B8 FF

        Note that for 200, C8 is a negative number, so the 00 is required to make it so that C8 00 is positive.

        Your post contradicts itself...

        Also, it works for all your test cases !

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11136246]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2024-04-23 07:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found