Quick Tip #20: Way off base

Want to use numbers that are represented in something other than base 10? That’s no problem in Perl 6. Some languages throw you a bone with binary, octal, or hexadecimal conversions, but what if you want base 17? Or, better yet, base 36?

First, for Real numbers (or, non-complex numbers), I have the base command:

$ perl6
> 137.base(2)
10001001
> 137.base(8)
211
> 137.base(16)
89
> 137.base(36)
3T

I can go up to base-36 because that’s how many digits and Latin letters the method uses. Those convert number types to strings.

I can go the other way too. The :DIGIT(string) syntax converts strings to numbers:

> :2('10001001')
137
> :8('211')
137
> :16('89')
137

These assume that the string is a number represented that the radix after the colon. These return a Perl 6 number, which you can display in any base that you like.

From there I can make some one-liners to convert bases. I’ve done this for Perl 5, and now I have them for Perl 6:

alias o2b="perl6 -e 'say sprintf q/:2(%b)/, :8(@*ARGS.shift)'"
alias o2d="perl6 -e 'say sprintf q/:10(%d)/, :8(@*ARGS.shift)'"
alias o2h="perl6 -e 'say sprintf q/:16(%x)/, :8(@*ARGS.shift)'"

alias d2b="perl6 -e 'say sprintf  q/:2(%b)/, @*ARGS.shift'"
alias d2o="perl6 -e 'say sprintf  q/:8(%d)/, @*ARGS.shift'"
alias d2h="perl6 -e 'say sprintf q/:16(%x)/, @*ARGS.shift'"

alias h2b="perl6 -e 'say sprintf  q/:2(%b)/, :16(@*ARGS.shift)'"
alias h2o="perl6 -e 'say sprintf  q/:8(%o)/, :16(@*ARGS.shift)'"
alias h2d="perl6 -e 'say sprintf q/:10(%d)/, :16(@*ARGS.shift)'"

4 comments

  1. If you give your aliases a parameter that is not a number, or not a number of the right base, you may get back a LTA error message which looks confusing and also seemss fixable by changing a few characters of the program.

    $ alias o2b=”perl6 -e ‘say sprintf q/:2(%b)/, :8(@*ARGS.shift)'”
    $ o2b 99
    Directive b not applicable for type Failure
    in any at /home/ron/.rakudobrew/moar-nom/install/share/perl6/runtime/CORE.setting.moarvm line 1

    What appears to be happening is that :8() is returning type Failure which does not throw an exception until evaluation.

    If we evaluate earlier with +:8() then:
    $ alias o2b=”perl6 -e ‘say sprintf q/:2(%b)/, +:8(@*ARGS.shift)'”
    $ o2b 99
    Cannot convert string to number: base-8 number must begin with valid digits or ‘.’ in ‘:8’ (indicated by ⏏)
    in block at -e line 1

    Actually thrown at:
    in block at -e line 1

    $ o2b abc
    Cannot convert string to number: base-8 number must begin with valid digits or ‘.’ in ‘:8’ (indicated by ⏏)

    $ o2b 42
    :2(100010)

    Which looks like better handling with just a little extra effort.

    In the case of d2[boh] one may need to use +:10(@*ARGS.shift).

  2. The much simpler way to write that is as:

        @*ARGS[0].parse-base(8).base(2)
    

    Instead of that ugly sprintf concoction.

    .parse-base also handles negative numbers, unlike the :16() radix literal syntax.

Leave a Reply to Ronald Schmidt Cancel reply

Your email address will not be published. Required fields are marked *