Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Proper creation of a negative number

by insta.gator (Novice)
on Jul 08, 2015 at 13:23 UTC ( [id://1133717]=perlquestion: print w/replies, xml ) Need Help??

insta.gator has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks. I have a script that parses numeric values from a file. We have discovered that when a negative value exists in the file, it is displayed with the negative sign following the number rather than preceding the number. My script seems to be just ignoring the negative sign. Here is the code

@line = split (/\s+/, $line); # Split line on any amount of + whitespace $TFCNTL_Tax = @line[8]; $TFCNTL_Tax =~ s/(\$|,)//g; # Get rid of $ and comma +s push(@TFCNTL_Tax,$TFCNTL_Tax); # Save value for later print "TFCNTL_Tax=@TFCNTL_Tax\n\n";

So for example, the value of @line8 may be 7.89-. Later in the script we format the value as follows:

$total = sprintf("%.2f", @TFCNTL_Tax[$i]);  # Format number for floating point math

The result is that the negative number becomes a positive number.

I am assuming that we need to do some sort of test to determine if there is a minus sign following the number and then alter the variable to make it an actual negative number. Just not sure how to go about this. Can someone please help me with the best way to fix this?

Thanks!

Replies are listed 'Best First'.
Re: Proper creation of a negative number
by toolic (Bishop) on Jul 08, 2015 at 13:31 UTC
    Use the substitution operator to move a minus sign at the end of the string (if any) to the front of the string:
    use warnings; use strict; while (<DATA>) { chomp; s/(.+)-$/-$1/; print "$_\n"; } __DATA__ 1.05 -5.66 7.89-

    Outputs:

    1.05 -5.66 -7.89
      Maybe with a regex that is slightly better at finding numbers, e.g. [.0-9]+\- versus 'anything-at-all' that is followed by a minus sign. Seems that the regex as writ could slurp up everything until the first minus.
Re: Proper creation of a negative number
by kcott (Archbishop) on Jul 08, 2015 at 15:24 UTC

    G'day insta.gator,

    If you're using Perl v5.14 (or later), you can do all those operations in one statement.

    I've chosen transliteration (y///), for the '$' and ',' removal, because it's quicker than substitution (s///); although, you could stick with substitution if you want.

    If you do stay with s///, consider the character class '[\$,]' in favour of the alternation '\$|,'. I expect, but don't know for certain, that the former would quicker: Benchmark if you're interested.

    Anyway, v5.14 introduced the '\r' modifier which allows you to chain s/// and y/// operations. Here's my test code:

    #!/usr/bin/env perl use v5.14; use warnings; my @TFCNTL_Tax; while (<DATA>) { $TFCNTL_Tax[@TFCNTL_Tax] = (split)[8] =~ y/$,//dr =~ s/^(.*)-$/-$1 +/r; } say for @TFCNTL_Tax; __DATA__ 0 0 0 0 0 0 0 0 $1,234.56 0 0 0 0 0 0 0 0 0 $7,890.12- 0 0 0 0 0 0 0 0 0 -$3,456.78 0 0 0 0 0 0 0 0 0 $-9,012.34 0

    Output:

    1234.56 -7890.12 -3456.78 -9012.34

    If you chain two substitutions instead:

    $TFCNTL_Tax[@TFCNTL_Tax] = (split)[8] =~ s/[\$,]//gr =~ s/^(.*)-$/ +-$1/r;

    the output remains the same.

    See also: perlre: Modifiers (for /r); perlop: Quote-Like Operators (for y///); perlop: Regexp Quote-Like Operators (for s///).

    -- Ken

      ... with s///, consider the character class '[\$,]' in favour of the alternation '\$|,'. I expect, but don't know for certain, that the former would quicker ...

      I certainly haven't Benchmark-ed it, but I think that with trie optimization for alternations (introduced with 5.10?), a humble alternation like  a|b|c gets compiled to  [abc] anyway. Even if not, any difference in speed would not, I think, be perceptible unless you were doing a gazillion matches.

      ... the '\r' modifier which allows you to chain s/// and y/// operations.

      I knew about the  /r modifier, but I hadn't really thought about chaining these operations in this way! Come to think of it, such chaining was probably a signficant motive for adding this feature. Granted, the left-associativity of  =~ !~ looks a bit strange in conjunction with the right-assoc. of assignment (the RHS ends up in the middle of the expression), but I can live with that. Again, I've done no Benchmark-ing, but if forced, I think I'd say this trick was more likely to yield speed increases than attention to character class vs. alternation (at least in simple cases).


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

        You appear to have taken a side-issue and thrust it into the limelight.

        The main focus of my post was about chaining. The opening sentence talked about performing all operations in a single statement. The code was all about chaining. The three documentation links I provided at the end lead to information about chaining.

        And then there were side-issues:

        I pointed out that I had used transliteration, instead of substitution (which the OP's code had), because it was quicker. That was an unequivocal statement.

        [I didn't go into more depth on this issue as it detracted from the chaining operations I was demonstrating. However, it is documented in "perlperf - Perl Performance and Optimization Techniques" (specifically under "Search and replace or tr").]

        I then went on to say that, if the OP chose not to use transliteration, then a character class might be quicker than alternation. I said "I expect" and "don't know for certain"; and went on to suggest benchmarking. There was no unequivocal statement here.

        -- Ken

Re: Proper creation of a negative number
by pme (Monsignor) on Jul 08, 2015 at 13:40 UTC
    You can check the existence of minus sign and then prepend the output if necessary.
    $total = sprintf("%s%.2f", @TFCNTL_Tax[$i] =~ /(\-)/ ? $1 : undef, @TF +CNTL_Tax[$i]);

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1133717]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (8)
As of 2024-03-28 11:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found