Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

(tye)Re4: The Definitive Unit Conversion Script

by tye (Cardinal)
on Dec 14, 2002 at 06:53 UTC ( #219836=note: print w/ replies, xml ) Need Help??


in reply to Re^2: The Definitive Unit Conversion Script
in thread The Definitive Unit Conversion Script

The interface I would want would be something like:     my @new= ConvertTo( $toUnits, $fromUnits, @old );
which would convert the numbers in @old from $fromUnits to $toUnits and return the results. So:

# <--------- inches ---------><----- ft -----> my @inches= ConvertTo( 'in', 'ft', 1, 2, 3 ); # @inches is now ( 12, 24, 36 )
Note that it is "to" followed by "from" so the unit name is closest to the numbers that are/will be in those units.

If I want to do a lot of conversions but not all at once, then:

my $toInFromFt= ConvertTo( 'in', 'ft' ); while( <IN> ) { chomp; print OUT $toInFromFt->($_), $/; }
And I'd probably support aliases for units and include a "long alias" for every unit: "inch", "feet", "meter", "centimeter", "Centigrade", "Farenheit", "Kelvin", "second", "hour", etc. just to avoid confusion.

I'd probably put the unit data after __DATA__ so you could just append more units to be able to support them.

The "all possible conversions" is interesting for interactive exploration, but I don't see nearly as much use for it as requesting a specific conversion.

For finding the conversion, I'd look for a direct conversion, but if there isn't one, form the list of all possible conversions and then repeat for each of those:

my @table = ( #### temperature [ c => f => sub { ($_[0] * 9/5) + 32 }, sub { ($_[0] - 32) * 5/9 }, ], [ c => k => sub { $_[0] + 273.16 }, sub { $_[0] - 273.16 }, ], #### mass/weight [ kg => g => 1000 ], [ floz => g => 30 ], [ lbs => kg => 0.4536 ], #### distance [ ft => m => 0.3048 ], [ ft => in => 12 ], [ in => cm => 2.54 ], [ m => cm => 100 ], [ yd => m => 0.9144 ], [ km => m => 1000 ], [ mile => km => 1.609347 ], ); my %table; for my $conv ( @table ) { my( $from, $to, $conv, $rev )= @$conv; if( exists $table{$from}{$to} ) { warn "Duplicate conversions to $to from $from.\n"; } $table{$from}{$to}= $conv; if( $rev ) { if( exists $table{$from}{$to} ) { warn "Duplicate conversions to $from from $to.\n"; } $table{$to}{$from}= $rev; } } # Handle reverse conversions when a better one isn't provided: for my $conv ( @table ) { my( $from, $to, $conv )= @$conv; if( ! ref($conv) && ! exists $table{$to}{$from} ) { $table{$to}{$from}= sub { $_[0] / $conv }; } } sub FindConversionPathTo { my( $dest, $source )= @_; my( @sol ); $source= { $source => "$source " }; while( ! @sol ) { for my $src ( keys %sources ) { if( exists $table{$src}{$dest} ) { $source{$src} .= "$dest "; push @sol, $src; } else { for my $dest ( keys %{$table{$src} ) { if( ! exists $source{$dest} ) { $source{$dest}= $source{$src} . "$dest "; } } } } } # Pick one of the solutions at random: (: return split ' ', (@source{@sol})[rand @sol]; }
Untested (I hope you don't mind).

        - tye


Comment on (tye)Re4: The Definitive Unit Conversion Script
Select or Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://219836]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (9)
As of 2015-07-05 14:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (67 votes), past polls