There's more than one way to do things PerlMonks

### math problems

by mmittiga17 (Scribe)
 on Mar 28, 2011 at 21:56 UTC 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

```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.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://896037]
Approved by kennethk
Front-paged by bart
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2018-11-15 05:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My code is most likely broken because:

Results (180 votes). Check out past polls.

Notices?