gannett has asked for the wisdom of the Perl Monks concerning the following question:

Learned monks ... I am working on some very long Ints using the textural representation of a number and summing the digits. For example SumDigits(312023) = 3+1+2+0+2+3 = 11. Sometimes there is a need to split very long strings and interpret those as numbers separately. A small example 312023 => 321 and 023. Perl is generally quite forgiving about moving between strings and integers but unfortunately this stumbles on a feature from the dark ages of computing. Consider
perl -e 'print 312023," ",312," ",23,"\n";' 312023 312 23
and
perl -e 'print 312023," ",312," ",023,"\n";' 312023 312 19
In the second example the third part "023" is interpreted as octal ( base 7 ) and becomes 2*8+3 decimal 19. I am neutral about 0x23 interpreted as hexadecimal but can this ancient octal feature of perl be switched off ?

Replies are listed 'Best First'.
Re: How to Switch off octal interpretation of literal ?
by LanX (Saint) on Apr 07, 2018 at 15:24 UTC
    A hint from the "dark ages of computing": ;-)

    Use strings!

    DB<3> p 300 . 023 # octal 30019 DB<4> p "300" . "023" # "decimal" 300023 DB<5> p "300" + "023" # decimal 323

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Wikisyntax for the Monastery

Re: How to Switch off octal interpretation of literal ?
by haukex (Archbishop) on Apr 07, 2018 at 15:27 UTC
    can this ancient octal feature of perl be switched off ?

    I don't think so (and BTW, octals are still useful today in e.g. chmod).

    But it sounds more like an XY Problem to me - it appears you're generating Perl source code. If you're doing that, why not generate the numbers as strings instead? When converting strings to numbers, leading zeros are ignored.

    $ perl -wMstrict -le 'print 0+"023"' 23

    Could you show the code that is generating your Perl code? I curious why there is need to chop numbers up and then interpret them as integers instead of strings.

Re: How to Switch off octal interpretation of literal ?
by jimpudar (Pilgrim) on Apr 07, 2018 at 16:23 UTC

    I think Rolf's answer is better than this one as it more clearly explains why you were getting the octal interpretation, but here is a quick one liner to do what you want.

    Here I am using autosplit mode with the field separator set to the empty string and using reduce from List::Util:

    $ perl -MList::Util=reduce -wlF'' -e 'print reduce { $a + $b } @F' 321023 11 321 6 023 5

    With this technique you can just type your numbers at the command line like I have here, or you could put all your long ints into a file separated by newlines and pass it to Perl as the first argument.

    Update: After reading AnomalousMonk's post below, I realized using reduce here is a bit silly. With sum, the code is even more simple:

    $ perl -MList::Util=sum -wlF'' -e 'print sum @F'

    Best,

    Jim

Re: How to Switch off octal interpretation of literal ?
by karlgoethebier (Abbot) on Apr 08, 2018 at 08:49 UTC

    Don't switch it off - bypass it. From Re: removing leading 0's: perl -e 'printf( "%o\n", 023 )'. If this is what you meant.

    Best regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: How to Switch off octal interpretation of literal ?
by gannett (Novice) on Apr 07, 2018 at 16:30 UTC
    Thanks so much for the "string" naked number pointers. This indicates that my code needs to be more disciplined around the conversion process rather than just taking it for granted or using this monster.
    sub sdtt() { #sum of digits on Text number local $t =0; map { $t+= $_ } split //, sprintf("%d",$_[0]); return $t; }

      Update: Oops... This post was intended as a reply to this post, not to LanX. | Reparented.

      Some general thoughts on "this monster" (if you feel you need a function at all):

      sub sdtt() { #sum of digits on Text number local $t =0; map { $t+= $_ } split //, sprintf("%d",$_[0]); return $t; }
      • sub sdtt() { ... } Don't define a subroutine with a prototype that requires the subroutine to take no arguments and then call the subroutine with an argument. I suspect you are calling the subroutine in a way that defeats prototyping | prototype checking, e.g.
            &sdtt($n);
        or some such. Please don't use prototypes unless you know exactly what they do. Please see Far More than Everything You've Ever Wanted to Know about Prototypes in Perl -- by Tom Christiansen. If you use prototypes, please don't defeat them without good reason.
      • local $t = 0; Please don't local-ize package-global variables in subroutines (unless you really need to). You'll give yourself a headache. Use my (lexical) variables instead.
      • In this particular case, you don't even need a local or a lexical variable. Using List::Util::sum() makes things a bunch simpler:
        c:\@Work\Perl\monks>perl -wMstrict -le "use List::Util qw(sum); ;; sub sdtt { return sum split //, $_[0]; } ;; for (@ARGV) { print qq{sum of digits of $_ == }, sdtt($_); } " 321023 321 023 sum of digits of 321023 == 11 sum of digits of 321 == 6 sum of digits of 023 == 5
        (split implicitly stringizes its EXPR argument.) (Update: List::Util has been core since Perl version 5.8. Present in more recent versions of this module, the function  sum0() may be more useful to you since it returns a sum of 0 for an empty string.)

      Update: And another thing...
          map { $t+= $_ } split //, sprintf("%d",$_[0]);
      This is a philosophical nit I'm picking, but I would use for in this type of loop:
          $t += $_ for split //, ...;
      I still don't understand why anyone would prefer to use map in a situation like this, i.e., purely for its side-effect(s).


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

        Thanks - guidance much appreciated. The sub() {.. definition } just an old bad habit.
Re: How to Switch off octal interpretation of literal ? (learn perl)
by Anonymous Monk on Apr 08, 2018 at 04:55 UTC

    How to Switch off octal interpretation of literal ?

    Learn perlnumber, its only perl