in reply to More elegant way than multiple "if"?
Your instinct to avoid a cascade of if statements is correct. That leads to hard to maintain code. There are some subtleties for a general solution however and in a production context you would want to write a test suite before you start implementing a solution - not least so that you have a good idea of where all the edge cases are.
The following code uses a couple of functions to change to and from float values:
use strict; use warnings; while (<DATA>) { my ($first, $second) = split; next if !$second; my $diff = ToUnit(ToFloat($first) - ToFloat($second)); print "$first - $second = $diff\n"; } sub ToUnit { my ($value) = @_; my $unitIndex = 0; my @units = ('', qw( k M G T)); my $neg = $value < 0; $value = -$value if $neg; while ($value >= 1000 && $unitIndex < $#units) { $value /= 1000; ++$unitIndex; } $value = -$value if $neg; return "$value$units[$unitIndex]"; } sub ToFloat { my ($str) = @_; my ($value, $unit) = $str =~ /([\d.+-]+)\s*([kMGT]?)/; my %mul = (k => 1e3, M => 1e6, G => 1e9, T => 1e12); my $neg = $value < 0; $value = -$value if $neg; $value *= $mul{$unit} if $unit && exists $mul{$unit}; $value = -$value if $neg; return $value; } __DATA__ 324k 324k 440k 533k 23T 224G 42G 42G 1.9T 709G 294k 294k 684k 684k 492k 492k 62M 64M 48k 41M 34M 433k 317k 812k
Prints:
324k - 324k = 0 440k - 533k = -93k 23T - 224G = 22.776T 42G - 42G = 0 1.9T - 709G = 1.191T 294k - 294k = 0 684k - 684k = 0 492k - 492k = 0 62M - 64M = -2M 48k - 41M = -40.952M 34M - 433k = 33.567M 317k - 812k = -495k
Note that K got changed to k. This code would be fairly easy to extend to handle standard SI suffixes, but that is left as an exercise for the learner.
|
|---|
| Replies are listed 'Best First'. |
|---|