in reply to negative numbers when doing multiplications?

With some small fixes to your code I do get a (large) positive number, namely 2348273369088 (I'm on a 64bit system, if that matters).

Things you can try: use bigint (see bigint), and use ordinary print instead of printf() for debugging.

Finally your hash access is unnecessary complicated - instead of the grep you can just access $iupac_dgn{$residues} directly.

The simplified code looks like this:

#!/usr/bin/perl use strict; use warnings; use integer; my %iupac_dgn; my @iupac_code = ('M','R','W','S','Y','K','V','H','D','B','N'); my @iupac_den = ('2','2','2','2','2','2','3','3','3','3','4'); @iupac_dgn{@iupac_code}=@iupac_den; my $string = 'GGNMDNNSNNNNDBNVWVSMNNHYNBNG'; my @residues = split(//, $string); my $degeneracy = 1; foreach my $residues(@residues){ $degeneracy *= $iupac_dgn{$residues} || 1; } printf "%28s, %30s\n", $string, $degeneracy;
Perl 6 - links to (nearly) everything that is Perl 6.

Replies are listed 'Best First'.
Re^2: negative numbers when doing multiplications?
by chuckbutler (Monsignor) on Mar 26, 2010 at 14:03 UTC

    If you are on a 32-bit system, you must use Math::BigInt. The following returns 2348273369088.

    #!/usr/bin/perl use strict; use warnings; use integer; use Math::BigInt; my %iupac_dgn; my @iupac_code = ('M','R','W','S','Y','K','V','H','D','B','N'); my @iupac_den = ('2','2','2','2','2','2','3','3','3','3','4'); @iupac_dgn{@iupac_code}=@iupac_den; my $string = 'GGNMDNNSNNNNDBNVWVSMNNHYNBNG'; my @residues = split(//, $string); my $degeneracy = Math::BigInt->new( 1 ); foreach my $residues(@residues){ $degeneracy *= $iupac_dgn{$residues} || 1; } printf "%28s, %30s\n", $string, $degeneracy;

    Update: I will concur with Tye as long as the result is less than 2 ** 49 on a 32b machine/implementation. Thanks.

    Good Luck. -c

      If you are on a 32-bit system, you must use Math::BigInt.

      Don't be foolish. :) Just don't use the stupid integer.pm module:

      #!/usr/bin/perl use strict; use warnings; # use integer; my %iupac_dgn; my @iupac_code=('M','R','W','S','Y','K','V','H','D','B','N'); my @iupac_den=('2','2','2','2','2','2','3','3','3','3','4'); @iupac_dgn{@iupac_code}=@iupac_den; my $string = 'GGNMDNNSNNNNDBNVWVSMNNHYNBNG'; my @residues = split( //, $string ); my $degeneracy = 1; foreach my $residues( @residues ) { if( grep( m/^$residues$/, keys %iupac_dgn ) ) { my $factor = $iupac_dgn{$residues}; $degeneracy = ($factor * $degeneracy); } } printf "%28s, %30d", $string, $degeneracy; __END__ GGNMDNNSNNNNDBNVWVSMNNHYNBNG, 2348273369088

      - tye        

        Part of the problem here may also be the printf "%d".  I just tried it (without use integer) on a 32-bit system/perl*, and the printf simply outputs -1, while print $degeneracy outputs the correct value without problems.

        (AFAICT (i.e. using ltrace), Perl comes with its own printf implementation, and doesn't call the one provided by the system's libc, so this should be system-independent.)

        ___

        * i686-linux, compilation settings from perl -V:

        intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +2 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8