http://www.perlmonks.org?node_id=11136253


in reply to Re^5: 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)

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

Replies are listed 'Best First'.
Re^7: Split any number into string of 8-bit hex values (=1 byte) (updated)
by AnomalousMonk (Bishop) on Aug 30, 2021 at 22:00 UTC

    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:  <%-{-{-{-<

Re^7: Split any number into string of 8-bit hex values (=1 byte)
by AnomalousMonk (Bishop) on Aug 30, 2021 at 22:53 UTC

    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:  <%-{-{-{-<

      Hey, I like regex fireworks :)

        So do I, but it's a guilty pleasure!


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

Re^7: Split any number into string of 8-bit hex values (=1 byte)
by tybalt89 (Prior) on Aug 30, 2021 at 22:41 UTC

    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.

      Note that for 200, C8 is a negative number, so the 00 is required to make it so that C8 00 is positive.
      Ah, that might be the reason for that odd trailing '00' in the OP

        How does an 8-bit register in an I2C device "know" that an 0xc8 byte started out as 20010 or as -5610? One can make similar arguments about 16- and 32-bit registers.

        I share the misgivings expressed by LanX here.


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

Re^7: Split any number into string of 8-bit hex values (=1 byte)
by tybalt89 (Prior) on Aug 30, 2021 at 21:02 UTC

    Your post contradicts itself...

    Also, it works for all your test cases !