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

Hi monks, I found a strange thing:
print oct(0xff) #173!!! print oct('0xff') #255 print oct(0b10000) #14!!! print oct('0b10000) #16 print hex(ff) #255 correctly! print hex('ff') #255
why?

Replies are listed 'Best First'.
Re: ' or no?
by ikegami (Patriarch) on Dec 28, 2006 at 02:48 UTC

    oct accepts the octal, hex or binary representation of a number, a string, as argument. That string is converted to a number. Only pass strings to oct. It doesn't make sense to pass numbers to oct.

    • oct(0xFF) is the same thing as oct(255). oct requires a string, so 255 is converted to a string, and oct("255") == 173.
    • oct(0b10000) is the same thing as oct(16). oct requires a string, so 16 is converted to a string, and oct("16") == 14.
    • When use strict; is not used, barewords that aren't function calls are treated as string literals. ff is therefore the same thing as 'ff'.
    #!perl -l print 0255; # 173 print oct('255'); # 173 print oct(255); # 173 print oct(0xFF); # 173 print oct(0b11111111); # 173 print oct(250+5); # 173 print 255; # 255 print 0xFF; # 255 print 0b11111111; # 255 print 250+5; # 255 print 016; # 14 print oct('16'); # 14 print oct(16); # 14 print oct(0x10); # 14 print oct(0b00010000); # 14 print oct(10+6); # 14 print 16; # 16 print 0x10; # 16 print 0b00010000; # 16 print 10+6; # 16
      In other words, a bare 0xFF is converted to 255 by the parser before oct ever sees it. (I'm not sure if this conversion actually happens, but intuitively that's what's happening)

        I'm not sure if this conversion actually happens

        Yes, it does. A more precise wording of what happens is: "The Perl literal 0xFF is converted to the numerical value 255 by the parser before oct ever sees it."

        oct, requiring a string, converts the numerical value 255 to the string value 255. Doing it's job, oct then converts the string value 255 to the numerical value 173.

      But that means oct convert a string to a number?strange logic.and according to perl theroy,number and string are one type "scalar".
      Anyway,thanks for your answer!

        Strings, numbers and many other things can be placed in a scalar. Not all scalars are numbers. Not all scalars are strings. Perl will implicitely convert back and forth as needed, possibly resulting in warnings.

        print 2+3; # Number converted to string. print 'a'.3; # N->S print '2'+3; # S->N, N->S print 'z'+3; # S->N (warn), N->S print 3+undef; # U->N (warn), N->S print ''.undef; # U->S (warn) print \$a; # R->S print \$a+0; # R->N->S
        Yes, but if you say $scalar = 0123 (using an octal constant) the number assigned is 83, and the string value of $scalar is also "83". All perl does for you is decimal to string conversion, so there's the oct() function to convert other (string!) representations of numbers into numbers.

        Actually, it's not "strange logic," after all "numbers" and "characters" are just human-readable strings representing the underlying bit representations; every time you type $x = 1234;, the tokenizer converts it to the underlying binary representation. The tokenizer also converts $y&nbps;= '1234'; to a binary form. oct and hex merely make the string to number conversion explicit, in the same way you would use sprintf|sscanf in C or ENCODE|DECODE in old (pre-Fortran 77) dialects of Fortran (now, you would use write|read). Perl automatically "stringifies" and "numerifies" based on context; print needs strings as inputs, so Perl automatically converts numbers to strings. sin needs a numerical argument, so Perl will convert a string to its numerical representation.

        emc

        At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.

        —Igor Sikorsky, reported in AOPA Pilot magazine February 2003.
Re: ' or no?
by logie17 (Friar) on Dec 28, 2006 at 18:45 UTC
    This is interesting. As I've painfully learned from experience , the use of strict would prevent you from even allowing you to pass bare words to oct. Maybe I'm impetuous, but the perldocs are rather vague that a string must be passed to oct.

    Cheers
    s;;5776?12321=10609$d=9409:12100$xx;;s;(\d*);push @_,$1;eg;map{print chr(sqrt($_))."\n"} @_;