Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

math problems

by mmittiga17 (Scribe)
on Mar 28, 2011 at 21:56 UTC ( #896037=perlquestion: print w/replies, xml ) Need Help??
mmittiga17 has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, Having problems adding values pulled from a string. I keep getting negative total when there are no negative numbers found in the file. I am sure it has something to do with my use of sprintf. Can someone take a peek at my code and advise where I am going wrong. Much thanks!!!

open(IN,"$inFile"); while(defined($line = (<IN>))){ $key=substr($line,34,1); if($key eq "7"){ $VAL1 = substr($line,137,13); $VAL2 = substr($line,124,13); $VAL3 = substr($line,56,15); $TOT1 = sprintf '%020d',$TOT1+$VAL1 ; $TOT2 = sprintf '%020d',$TOT2+$VAL2 ; $TOT3 = sprintf '%020d',$TOT3+$VAL3 ; #print "$key \n"; } if($key eq "8"){ $VAL4 = substr($line,43,13); $VAL5 = substr($line,124,13); $VAL6 = substr($line,56,15); $TOT4 = sprintf '%020d',$TOT4+$VAL4 ; $TOT5 = sprintf '%020d',$TOT5+$VAL5 ; $TOT6 = sprintf '%020d',$TOT6+$VAL6 ; #print "$key \n"; } $TOT1 = sprintf '%020s',0 if ($TOT1 eq ""); $TOT2 = sprintf '%020s',0 if ($TOT2 eq ""); $TOT3 = sprintf '%020s',0 if ($TOT3 eq ""); $TOT3 = sprintf '%020s',0 if ($TOT4 eq ""); $TOT4 = sprintf '%020s',0 if ($TOT5 eq ""); $TOT5 = sprintf '%020s',0 if ($TOT6 eq ""); }

Replies are listed 'Best First'.
Re: math problems
by ikegami (Pope) on Mar 28, 2011 at 22:04 UTC
    Are your numbers over 2 billion? %d uses a signed native integer, usually 32 bit of 64 bit in size. Use %.0f instead.
    $ perl -E'printf "%d\n", 2**34' -1 $ perl -E'printf "%.0f\n", 2**34' 17179869184
Re: math problems
by kennethk (Abbot) on Mar 28, 2011 at 22:11 UTC
    You are likely having a problem with hitting the upper limit of signed native integers. For example, printf '%020d', 2**31; outputs -0000000002147483648 on my 32-bit MS machine and printf '%020d', 2**63; ouptuts -9223372036854775808 on my 64-bit Linux box.

    I would also comment that when you are asking folks to diagnose a problem with a specific input file, providing that input (wrapped in code tags) can be very helpful.

Re: math problems
by BrowserUk (Pope) on Mar 28, 2011 at 22:24 UTC

    Try %u instead of %d:

    printf "%d\n", 9223372036854775808;; -9223372036854775808 printf "%u\n", 9223372036854775808;; 9223372036854775808

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I suspect this will only mask this issue for the OP. At best, this give the OP a factor of two improvement before he hits the ceiling, and then it transforms an obvious error to a silent one. For example, the code:

      printf "%020u\n%020u\n%020u\n", 9223372036854775808,20000000000000000000,99999999999999999999

      outputs under 64-bit

      09223372036854775808 18446744073709551615 18446744073709551615

      and under 32-bit

      00000000004294967295 00000000004294967295 00000000004294967295

      The swapping to %020.0f puts you at the whims of round-off, with 32-bit yielding

      09223372036854775800 20000000000000000000 100000000000000000000

      and 64-bit yielding

      09223372036854775808 20000000000000000000 100000000000000000000

      That round-off might well be acceptable depending on the specific numbers involved and required accuracy; if not the OP will likely have to resort to Math::BigInt or equivalent.

        I suspect this will only mask this issue for the OP.

        Hm. I don't consider doubling the usable range "masking the problem". More 'taking full advantage of the built-in capabilities whilst dodging the cumbersome and slow bullet of arbitrary precision' until (and if) it is actually required.

        I consider moving to Math::BigInt a very last resort. There are Math::Int64 and Math::Int128 to consider before then.

        But if his numbers will fit into the unsigned capabilities of the Perl he is using, it doesn't make any sense to seek alternatives for the sake of switching from %d to %u.

        I mean, if that is "just masking the problem", then why bother with IVs at all? Why not just have Perl do all math in arbitrary precision and no one would ever encounter these limitations?

        Oh right. I remember why now. Because arbitrary precision is dog slow and most of the time we don;t need it.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: math problems
by apl (Monsignor) on Mar 29, 2011 at 13:04 UTC
    Out of curiosity, did you ever try printing $VAL1, $VAL2, $VAL3 before, or $TOT1, $TOT2, $TOT3 after, the sprintfs?

    Then you would have had specific cases where the conversion worked, and where it didn't.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://896037]
Approved by kennethk
Front-paged by bart
help
Chatterbox?
NodeReaper polishes bones to Britney

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2018-05-21 09:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?