To expand a bit on frodo72's reply, if you change your code slightly to:
for ($mag=5.0;$mag<9.0;$mag=$mag+0.1){
$n{$mag}{0}=$n{$mag}{0.1}=$n{$mag}{0.3}=$n{$mag}{1}=0;
$n{$mag}{3}=$n{$mag}{10}=$n{$mag}{30}=$n{$mag}{1000}=0;
}
for ($mag=5.5; $mag<9.0; $mag=$mag+0.1){
print"$mag $n{$mag}{30}\n";
}
you'll see that you are not initializing what you think you are. The output of the above looks like this:
5.5 0
5.6 0
5.7 0
5.8 0
5.9 0
6 0
6.1 0
6.2 0
6.3 0
6.4 0
6.5
6.6
6.7
6.8
6.9
6.99999999999999 0
7.09999999999999 0
7.19999999999999 0
7.29999999999999 0
7.39999999999999 0
<truncated>
Try this:
use strict;
my @bin_labels = qw( 0 0.1 0.3 1 3 10 30 1000 );
{
my $step_size = 0.1;
my $start = 5.0;
my $finish = 9.0;
sub index_to_mag {
my $i = shift;
return $start + $i * $step_size;
}
sub mag_to_index {
my $mag = shift;
return sprintf "%.f", ($mag - $start) / $step_size;
}
}
my @n;
for ( my $i = 0; $i < mag_to_index( 9.0 ); ++$i ) {
$n[ $i ]{ $_ } = 0 for @bin_labels;
}
for ( my $mag = 5.5;
$mag < 9.0;
$mag = sprintf "%.1f", $mag + 0.1 ) {
printf "%.1f %f\n", $mag, $n[ mag_to_index( $mag ) ]{ 30 };
}
Afterthought: Maybe some clarification will make the code above more useful. I switched using a hash (%n) to using an array (@n), for the reasons that frodo72 already explained. In this case, there is a simple way to interconvert between array indexes and magnitudes; this is encapsulated in index_to_mag and mag_to_index. The frequent use of (s)printf takes care of avoiding round-off errors.
Update: Made proper closures out of mag_to_index and index_to_mag.
|