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


in reply to Definition of numerically equal and rationale for 'you' == 'me'

Numerically is the key word here. Perl attempts to convert strings to numbers via a very specific procedure:
  1. Start at the left. If the string is null, return 0.
  2. Move right character by character. If you see stuff that isn't numeric or whitespace, stop and return 0. Throw away whitespace. If you never see a number, return 0.
  3. When you find the first digit, collect characters as long as they still look like they belong to a number (Note that "0x" is a set of characters that could belong to a number). If you hit the end of the string, evaluate the number you have so far using these rules, and return that.
  4. If you see more "can't belong to this number" characters before you reach the end of the string (notice that this is contextual; e.g., if we'd gotten "0b", anything other any "1" or "0" can't belong), stop, evaluate whatever you have using these rules, and return that.
So you have two strings, each of which has no numbers in it at all. This means that they both are evaluated as empty strings, or zero, so they are equal.

If you had use warnings on, it would have told you that you were comparing two strings and that you would probably not get the intended results.

This is one of those cases where "what you meant" and "what you said" do not match, and the warning would have let you know that.

As a note, this is why "0 but true" - the "true zero" - is indeed that: a value equal numerically to zero, but when evaluated as part of a logical expression is true. It's zero by the number-collecting logic (start with "0", next character is " ", so end of number, value 0) and not a null string, undef, zero, or quoted zero by the test-for-false logic.

Edit: corrected number-detection logic: non-whitespace leading characters cause an immediate drop out with a zero value; whitespace doesn't count until you hit the number; any character that "can't belong" causes evaluation to stop. Added "0 but true" why-does-that-work explanation.

Replies are listed 'Best First'.
Re^2: Definition of numerically equal and rationale for 'you' == 'me'
by AnomalousMonk (Archbishop) on Mar 01, 2012 at 23:07 UTC

    Update: Now I look back, I see JavaFan made this exact point, so just see that reply.

    2. Move right character by character, and throw away stuff that doesn't look like a number. If you never see a number, return 0.
    3. When you find the first number, collect characters ...

    I would quarrel with those assertions. Perl only looks for a number in the left-most part of the string. With warnings:

    >perl -wMstrict -le "print 1 + 'x2x3x'; print 1 + '2x3'; " Argument "x2x3x" isn't numeric in addition (+) at -e line 1. 1 Argument "2x3" isn't numeric in addition (+) at -e line 1. 3
Re^2: Definition of numerically equal and rationale for 'you' == 'me'
by syphilis (Archbishop) on Mar 02, 2012 at 03:12 UTC
    Move right character by character

    As already noted, it's not actually done "character by character".
    If it were done that way 'nanosecond' == 'nanosecond' and 'informal' == 'formal' would both be true.
    Most places they're both false - though it generally depends upon the underlying libc (and, in some cases, perl bugginess).

    Cheers,
    Rob

      As already noted, it's not actually done "character by character".

      No, it was (correctly) said that skipping the leading non-number part isn't done at all.

      If it were done that way 'nanosecond' == 'nanosecond' and 'informal' == 'formal' would both be true.

      They are both true even though it's not done that way, so that's a useless statement.

        They are both true

        Where are they both true ?
        Did you even bother testing it ?

        Quite frankly, I regard it as an insult that you so quickly assume I'm just another moron.

        On Windows, perl-5.14.0:
        C:\>perl -e "print \"true\" if 'nanosecond'== 'nanosecond'" C:\>perl -e "print \"true\" if 'nanosecond'!= 'nanosecond'" true C:\>perl -e "print \"true\" if 'informal'== 'formal'" C:\>perl -e "print \"true\" if 'informal'!= 'formal'" true C:\>
        Should be the same most places.

        Rob