in reply to Converting "IV" from base 26

Looks like you are running afoul of the "special" argument handling that is done by the "print" function, when it tries to figure out whether its first arg is a file handle to print to, or simply the first value to be printed (to the current default output file handle) what ikegami said.

In any case, I think the better way to fix the original problem is like this:

sub v{ ord($_[0])-ord("A")+1 }
That is, your v() sub should return the correct index value for a given letter (between 1 and 26), so that it doesn't have to be fixed by the caller.

UPDATE: I wondered about your comment regarding "weight 1" vs. "weight 0"... are you sure about that? If we are talking about the column labels in a spreadsheet, "A" is col. 1, "Z" is 26, "AA" is 27, etc. That is, each letter "digit" has a "weight" of 1 (if I understand you terminology correctly).

In any case, an even better solution is to let the v() sub split the string and handle the power multiplication:

sub v { my (@letters) = split //, $_[0]; my $sum = 0; my $pwr = 1; while ( @letters ) { my $digit = ord( pop( @letters )) - ord("A") + 1; $sum += $digit * $pwr; $pwr *= 26; } return $sum; } print v("AB"),"\n";
prints "28", as it should, IMO.

Replies are listed 'Best First'.
Re^2: Converting "IV" from base 26
by Eimi Metamorphoumai (Deacon) on Jul 01, 2008 at 14:29 UTC
    Your code works, but there's no reason to create (and pop from) the separate @letters array. Additionally, by doing the multiplication first, we can get rid of the $pwr variable, and get to the much simpler (to my mind, at least),
    sub v { my $sum = 0; for (split //, $_[0]) { $sum *= 26; $sum += ord($_) - ord("A") + 1; } return $sum; }
    You could also factor out the ord("A") + 1 part into a separate variable, but I think it's a little easier to read this way (and the cost of the extra calls to ord is probably negligible).
Re^2: Converting "IV" from base 26
by ikegami (Patriarch) on Feb 09, 2009 at 19:27 UTC

    Looks like you are running afoul of the "special" argument handling that is done by the "print" function,

    That's completely wrong. It has nothing to do with print, and all to do with the meaninglessness of the space before opening paren.

    $ perl -le'sub f { print("@_"); } f (5) + 4' 5

    Or with warnings:

    $ perl -wle'sub f { print("@_"); } f (5) + 4' Useless use of addition (+) in void context at -e line 1. 5

    In the code in question,

    print (v('I')+1)*26 + v('V'), "\n";
    means
    print( v('I')+1 ) * 26 + v('V'), "\n";