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

I am doing a multiplication

#!/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 PRIMER_PAIRS "%28s, %30d", $string, $degeneracy;

for this particular string, it gives me a number with '-' in front '-1073741824'. am I doing something wrong here.. can anyone please help me

Thanks!

Replies are listed 'Best First'.
Re: negative numbers when doing multiplications?
by moritz (Cardinal) on Mar 26, 2010 at 13:30 UTC
    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.

      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        

Re: negative numbers when doing multiplications?
by almut (Canon) on Mar 26, 2010 at 14:29 UTC

    You apparently have a perl binary that only supports 32-bit integers.  And the value you compute (2348273369088) is much larger than 32 bits can hold. Represented as binary, it is:

    10_00100010_11000000_00000000_00000000_00000000

    So, it gets truncated

    11000000_00000000_00000000_00000000

    and as the leftmost (most significant) bit happens to be 1, and you used %d (= signed int) in printf, it is interpreted as a negative value (see Two's Complement). Effectively the same as

    printf "%d", 0b11000000_00000000_00000000_00000000 - 2**32; # -1073 +741824

    with a perl that supports ints larger than 32 bit.

Re: negative numbers when doing multiplications?
by Anonymous Monk on Mar 26, 2010 at 13:27 UTC