Reputation: 527
I was wondering if there is a way to convert a number like
100u 10km 300nm and so on
so that they are interpreted as:
100*10^-6 10*10^3 300*10^-6
I need to compare these numbers (100u, 10km, etc.). For example, if I want to compare 100u to 10u, that's ok; I just do the following, which is not correct but does the job:
$distance =~ s/(.*)u/$1/;
if ($distance >= $desired_distance) {
printf $distance;
}
where (.*)u
is the number, e.g. 100u. So I just remove the u
and then compare it with a number.
But, what if I have the number
1.45m
and I want to compare it with
1400u
The above thing wouldn't help.
Upvotes: 4
Views: 186
Reputation: 62019
Number::FormatEng will help to convert standard prefixes into numeric values:
use warnings;
use strict;
use Number::FormatEng qw(:all);
for (qw(100u 1.45m 1400u)) {
print "$_ ", unformat_pref($_), "\n";
}
Output:
100u 0.0001
1.45m 0.00145
1400u 0.0014
Upvotes: 12
Reputation: 104065
If there’s no CPAN module for that you can always roll your own:
my %units = (
m => 1,
km => 1000,
mm => 0.001,
);
for my $num (qw(10 10km 10mm)) {
$num =~ /(\d+)(\w+)?/;
my $value = $1;
my $unit = $2 || 'm';
print "$num = ", $value*$units{$unit}, " m\n";
}
Which outputs:
10 = 10 m
10km = 10000 m
10mm = 0.01 m
Plus tests and error handling. See TLP’s answer for some more idiomatic expressions.
Upvotes: 7
Reputation: 67900
Just make a subroutine to normalize your input, e.g.
sub normalize {
my %unit = (
u => 10^-6,
km => 10^3,
# etc
);
my $num = shift;
my ($base, $unit) = $num =~ /(\d+)(\S+)/;
$base *= $unit{$unit} // 1; # default to 1 if no unit is found
return $base;
}
Upvotes: 6