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!
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.
| [reply] [d/l] [select] |
|
#!/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
| [reply] [d/l] [select] |
|
#!/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
| [reply] [d/l] |
|
|
|
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.
| [reply] [d/l] [select] |
Re: negative numbers when doing multiplications?
by Anonymous Monk on Mar 26, 2010 at 13:27 UTC
|
| [reply] |
|
|