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

hello, Perl noob here.
Essentially I am writing a simple-ish program, for a class, to add, subtract, multiply, and divide two numbers. I have that taken care of. The last part of the program checks to see if the two numbers are multiples of each other (IE: 48 and 12 are.) I have a subroutine that looks like this:
sub is_integer_string { return $_[0] =~ /^\s*\+\-?\d+\s*$/; }

That was the only hint given for this assignment. This is my first experience with subroutines ever, and I'm straight up confused.
I assume that there should be an if statement of some sort. Figures the ONE day I am sick, I miss the important details...
Thanks

Replies are listed 'Best First'.
Re: finding multiples of two values
by Sewi (Friar) on Sep 01, 2009 at 07:37 UTC
    First, think about how to answer your question:
    Is 48 a multiple of 12?
    How do you do this (without a computer)? You divide 48 by 12...
    48 / 12 = 4
    Okay, "4" has no decimals (e.g. no "." or "," depending on your locale preference), so the answer is yes.

    Now let's do this in Perl:

    # First make the program know the two numbers: $Number1 = 48; $Number2 = 12; # Now divide the numbers: $Result = $Number1 / $Number2; # ...and look if we got a decimal:
    Let's stop for a moment. There are many ways to do the check, here are some of them:
    # Using your sub is_integer_string($Result) # Look for a . $Result =~ /\./; # Check if the number is the same as its integer part: $Result == int($Result)
    I prefer the last one. It compares the number to the integer part (e.g. everything before the . without rounding) and if they're the same - everything is fine.
    Of cause, you need to add a
    if (condition) { print "Yes"; } else { print "No"; }

    Regarding your subroutine... I think it won't work as you expect: Leaving the \s* alone, you're matching a + sign followed by zero or one - sign followed by numbers. +3 matches, but the string representation of a number doesn't include a leading + in Perl. Better to put [] around the \+ and \- (and keep the ?). This will match either a -, a + or nothing before the number.
    Perl could do a good part of the job for you if you want to match using a regexp:

    sub is_integer_string { my $N = $_[0] + 0; return $N =~ /^\-?\d+$/; }
    Any mathematical operation will see the input variable as a number (including everything Perl accepts here). Adding 0 means: Don't change my number at all, but force it to be a Perl number with a known syntax which could be matched easily.

    Update: Just noticed JavaFan's comment and he's right: modulo is the quickest way to do it, but all the others shown here also work.

      1.2e40 is an integer as well, and does contain a dot in stringified form.
        The . - test is ok for beginners who are doing their first programming steps, but I agree that it isn't good for productional software.
        Besides the module way, I prefer the $X == int($X) - which also works for 1.2e40
Re: finding multiples of two values
by Utilitarian (Vicar) on Sep 01, 2009 at 07:58 UTC
    You don't need an if statement because the expression
    $_[0] =~ /^\s*\+\-?\d+\s*$/
    is evaluated before the return.

    In a scalar context it returns the number of matches.

    Therefore as the regex is anchored start and end, if the supplied string is an integer the regex returns 1 otherwise 0, which are evaluated as true and false. Thus the above routine could be employed as follows

    if (is_integer_string($input){ do_integer_function($input); } else{ die "You must supply an integer\n"; }
    You need to check if the modulus of the numbers is zero, perhaps a has_remainder function?

    Hope that clarifies.

Re: finding multiples of two values
by JavaFan (Canon) on Sep 01, 2009 at 07:30 UTC
    What's that subroutine have to do with checking whether two numbers are multiples of each other? Just use the modulo operator (%), see the perlop manual page.
Re: finding multiples of two values
by hangon (Deacon) on Sep 01, 2009 at 11:07 UTC
    This is my first experience with subroutines ever, and I'm straight up confused.

    Ok, so you were sick the day they covered subroutines, I'll try to clear them up a bit. You were given a subroutine with some commonly used shortcuts. Here's a different example broken down into four versions that do exactly the same thing.

    # calling the subroutine. in this example the # first arg is a variable, second is a literal value my $arg1 = 100; my $return_value = add_these($arg1, 200); print $return_value; # subroutines receive arguments via an array named @_ # this version gets the args by array index sub add_these{ my $first = $_[0]; my $second = $_[1]; my $answer = $first + $second; return $answer; } # this one shifts values off the front of the array # note that @_ is implied if an array is not given as # the argument to shift. commonly seen as: # my $value = shift; sub add_these{ my $first = shift @_; my $second = shift @_; my $answer = $first + $second; return $answer; } # as shown here it is not necessary to assign the # arguments to an intermediate variable - you can # use them directly (however the extra variables # often makes the code more readable) sub add_these{ my $answer = $_[0] + $_[1]; return $answer; } # you don't even need to return a variable, you can # directly return the value calculated by an expression, # as shown here and in the "hint" example you were given sub add_these{ return $_[0] + $_[1]; }

    As for the multiples problem, you're looking for a boolean (true/false) value, represented as true = 1, false = 0. So your subroutine would determine if the arguments were multiples and return 1 if they are, 0 if they're not. And yes, use an if statement, (and the modulo operator as others suggested). There are other ways to do it, but no sense getting fancy till you have a handle on the basics.

Re: finding multiples of two values
by Anonymous Monk on Sep 01, 2009 at 07:05 UTC
    I see you're confused, but what is your question? How to write a subroutine? See perlintro, perlsub. How to determine multiples?

Re: finding multiples of two values
by Your Mother (Archbishop) on Sep 02, 2009 at 04:06 UTC

    I think JavaFan had it right but I didn't notice, since his reply didn't have code, till I wrote some. So…

    while ( <DATA> ) { chomp; my ( $first, $second ) = split; print "$first:$second --> ", multiple($first,$second) ? "yes" : "no", "\n"; } sub multiple { my ( $one, $two ) = @_; ! ( $one > $two ? $one % $two : $two % $one ); } __DATA__ 1 2 2 3 3 9 9 3 11 7 2 108 4 4
      Thanks guys. I finally got a chance to work on this.

      I just did the modulus route and it works. I had a somewhat of a basic clue of what to do, just needed an extra push.

      I agree though, I don't think a subroutine is necessary for this program. I need to look more into this modulus operator, it seems nifty. My first try resulted in a incorrect answer. It said that it was a multiple, even though the quotient was .5 (2 / 4), and when it said it wasn't a multiple when the quotient was 4 (48 / 12) I fixed it by flipping the operands. Just was an unexpected result. Something to research for sure.

      Anyways, thanks again guys.