[system] / trunk / webwork / system / courseScripts / Units.pm Repository:
ViewVC logotype

View of /trunk/webwork/system/courseScripts/Units.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (download) (as text) (annotate)
Thu Jun 14 17:08:51 2001 UTC (11 years, 11 months ago) by sam
File size: 15521 byte(s)
initial import

    1 #!/usr/math/bin/perl -w
    2 
    3 
    4 # This is the "exported" subroutine.  Use this to evaluate the units given in an answer.
    5 
    6 sub evaluate_units {
    7   &Units::evaluate_units;
    8 }
    9 
   10 # Methods for evaluating units in answers
   11 package Units;
   12 
   13 #require Exporter;
   14 #@ISA = qw(Exporter);
   15 #@EXPORT = qw(evaluate_units);
   16 
   17 
   18 # compound units are entered such as m/sec^2 or kg*m/sec^2
   19 # the format is unit[^power]*unit^[*power].../  unit^power*unit^power....
   20 # there can be only one / in a unit.
   21 # powers can be negative integers as well as positive integers.
   22 
   23     # These subroutines return a unit hash.
   24     # A unit hash has the entries
   25     #      factor => number   number can be any real number
   26     #      m      => power    power is a signed integer
   27     #      kg     => power
   28     #      s      => power
   29     #      rad    => power
   30     #      degC   => power
   31     #      degF   => power
   32     #      degK   => power
   33     #      perhaps other fundamental units will added later as well.
   34 
   35 
   36 my %fundamental_units = ('factor' => 1,
   37                      'm'      => 0,
   38                      'kg'     => 0,
   39                      's'      => 0,
   40                      'rad'    => 0,
   41                      'degC'   => 0,
   42                      'degF'   => 0,
   43                      'degK'   => 0
   44 );
   45 
   46 # This hash contains all of the units which will be accepted.  These must
   47 #be defined in terms of the
   48 # fundamental units given above.  If the power of the fundamental unit is
   49 #not included it is assumed to
   50 # be zero.
   51 
   52 my $PI = 4*atan2(1,1);
   53 
   54 my %known_units = ('m'  => {
   55                            'factor'    => 1,
   56                            'm'         => 1
   57                           },
   58                  'kg'  => {
   59                            'factor'    => 1,
   60                            'kg'        => 1
   61                           },
   62                  's'  => {
   63                            'factor'    => 1,
   64                            's'         => 1
   65                           },
   66                 'rad' => {
   67                            'factor'    => 1,
   68                            'rad'       => 1
   69                           },
   70                'degC' => {
   71                            'factor'    => 1,
   72                            'degC'      => 1
   73                           },
   74                'degF' => {
   75                            'factor'    => 1,
   76                            'degF'      => 1
   77                           },
   78                'degK' => {
   79                            'factor'    => 1,
   80                            'degK'      => 1
   81                           },
   82 # ANGLES
   83 # deg  -- degrees
   84 #
   85                 'deg'  => {
   86                            'factor'    => 0.0174532925,
   87                            'rad'       => 1
   88                           },
   89 # TIME
   90 # s     -- seconds
   91 # ms    -- miliseconds
   92 # min   -- minutes
   93 # hr    -- hours
   94 # day   -- days
   95 # yr    -- years  -- 365 days in a year
   96 #
   97                   'ms'  => {
   98                            'factor'    => 0.001,
   99                            's'         => 1
  100                           },
  101                   'min'  => {
  102                            'factor'    => 60,
  103                            's'         => 1
  104                           },
  105                   'hr'  => {
  106                            'factor'    => 3600,
  107                            's'         => 1
  108                           },
  109                   'day'  => {
  110                            'factor'    => 86400,
  111                            's'         => 1
  112                           },
  113                   'yr'  => {
  114                            'factor'    => 31557600,
  115                            's'         => 1
  116                           },
  117 
  118 # LENGTHS
  119 # m    -- meters
  120 # cm   -- centimeters
  121 # km   -- kilometers
  122 # mm   -- millimeters
  123 # micron -- micrometer
  124 # um   -- micrometer
  125 # nm   -- nanometer
  126 # A    -- Angstrom
  127 #
  128                  'km'  => {
  129                            'factor'    => 1000,
  130                            'm'         => 1
  131                           },
  132                  'cm'  => {
  133                            'factor'    => 0.01,
  134                            'm'         => 1
  135                           },
  136                  'mm'  => {
  137                            'factor'    => 0.001,
  138                            'm'         => 1
  139                           },
  140              'micron'  => {
  141                            'factor'    => 10**(-6),
  142                            'm'         => 1
  143                           },
  144                  'um'  => {
  145                            'factor'    => 10**(-6),
  146                            'm'         => 1
  147                           },
  148                  'nm'  => {
  149                            'factor'    => 10**(-9),
  150                            'm'         => 1
  151                           },
  152                   'A'  => {
  153                            'factor'    => 10**(-10),
  154                            'm'         => 1
  155                           },
  156 # ENGLISH LENGTHS
  157 # in    -- inch
  158 # ft    -- feet
  159 # mi    -- mile
  160 # light-year
  161 #
  162                  'in'  => {
  163                            'factor'    => 0.0254,
  164                            'm'         => 1
  165                           },
  166                  'ft'  => {
  167                            'factor'    => 0.3048,
  168                            'm'         => 1
  169                           },
  170                  'mi'  => {
  171                            'factor'    => 1609.344,
  172                            'm'         => 1
  173                           },
  174          'light-year'  => {
  175                            'factor'    => 9.46E15,
  176                            'm'         => 1
  177                           },
  178 # VOLUME
  179 # L   -- liter
  180 # ml -- milliliters
  181 # cc -- cubic centermeters
  182 #
  183                   'L'  => {
  184                            'factor'    => 0.001,
  185                            'm'         => 3
  186                           },
  187                  'cc'  => {
  188                            'factor'    => 10**(-6),
  189                            'm'         => 3,
  190                           },
  191                  'ml'  => {
  192                            'factor'    => 10**(-6),
  193                            'm'         => 3,
  194                           },
  195 # VELOCITY
  196 # knots -- nautical miles per hour
  197 #
  198               'knots'  => {
  199                            'factor'    =>  0.5144444444,
  200                            'm'         => 1,
  201                            's'         => -1
  202                           },
  203 # MASS
  204 # g    -- grams
  205 # kg   -- kilograms
  206 #
  207                   'g'  => {
  208                            'factor'    => 0.001,
  209                            'kg'         => 1
  210                           },
  211 # ENGLISH MASS
  212 # slug -- slug
  213 #
  214                'slug'  => {
  215                            'factor'    => 14.6,
  216                            'kg'         => 1
  217                           },
  218 # FREQUENCY
  219 # Hz    -- Hertz
  220 # kHz   -- kilo Hertz
  221 # MHz   -- mega Herta
  222 #
  223                  'Hz'  => {
  224                            'factor'    => 2*$PI,  #2pi
  225                            's'         => -1,
  226                            'rad'       => 1
  227                           },
  228                 'kHz'  => {
  229                            'factor'    => 1000*2*$PI,  #1000*2pi,
  230                            's'         => -1,
  231                            'rad'       => 1
  232                           },
  233                 'MHz'  => {
  234                            'factor'    => (10**6)*2*$PI,  #10^6 * 2pi,
  235                            's'         => -1,
  236                            'rad'       => 1
  237                           },
  238                 'rev'  => {
  239                       'factor'   => 2*$PI,
  240                       'rad'      => 1
  241                       },
  242                 'cycles'  => {
  243                       'factor'   => 2*$PI,
  244                       'rad'      => 1
  245                       },
  246 
  247 # COMPOUND UNITS
  248 #
  249 # FORCE
  250 # N      -- Newton
  251 # microN -- micro Newton
  252 # uN     -- micro Newton
  253 # dyne   -- dyne
  254 # lb     -- pound
  255 # ton    -- ton
  256 #
  257                  'N'  => {
  258                            'factor'    => 1,
  259                            'm'         => 1,
  260                            'kg'        => 1,
  261                            's'         => -2
  262                           },
  263             'microN'  => {
  264                            'factor'    => 10**(-6),
  265                            'm'         => 1,
  266                            'kg'        => 1,
  267                            's'         => -2
  268                           },
  269                  'uN'  => {
  270                            'factor'    => 10**(-6),
  271                            'm'         => 1,
  272                            'kg'        => 1,
  273                            's'         => -2
  274                           },
  275                'dyne'  => {
  276                            'factor'    => 10**(-5),
  277                            'm'         => 1,
  278                            'kg'        => 1,
  279                            's'         => -2
  280                           },
  281                  'lb'  => {
  282                            'factor'    => 4.45,
  283                            'm'         => 1,
  284                            'kg'        => 1,
  285                            's'         => -2
  286                           },
  287                 'ton'  => {
  288                            'factor'    => 8900,
  289                            'm'         => 1,
  290                            'kg'        => 1,
  291                            's'         => -2
  292                           },
  293 # ENERGY
  294 # J      -- Joule
  295 # kJ     -- kilo Joule
  296 # erg    -- erg
  297 # lbf    -- foot pound
  298 # cal    -- calorie
  299 # kcal   -- kilocalorie
  300 # eV     -- electron volt
  301 # kWh    -- kilo Watt hour
  302 #
  303                     'J'  => {
  304                            'factor'    => 1,
  305                            'm'         => 2,
  306                            'kg'        => 1,
  307                            's'         => -2
  308                           },
  309                  'kJ'  => {
  310                            'factor'    => 1000,
  311                            'm'         => 2,
  312                            'kg'        => 1,
  313                            's'         => -2
  314                           },
  315                 'erg'  => {
  316                            'factor'    => 10**(-7),
  317                            'm'         => 2,
  318                            'kg'        => 1,
  319                            's'         => -2
  320                           },
  321                 'lbf'  => {
  322                            'factor'    => 1.355,
  323                            'm'         => 2,
  324                            'kg'        => 1,
  325                            's'         => -2
  326                           },
  327                 'cal'  => {
  328                            'factor'    => 4.19,
  329                            'm'         => 2,
  330                            'kg'        => 1,
  331                            's'         => -2
  332                           },
  333                'kcal'  => {
  334                            'factor'    => 4190,
  335                            'm'         => 2,
  336                            'kg'        => 1,
  337                            's'         => -2
  338                           },
  339                 'eV'  => {
  340                            'factor'    => 1.60E-9,
  341                            'm'         => 2,
  342                            'kg'        => 1,
  343                            's'         => -2
  344                           },
  345                 'kWh'  => {
  346                            'factor'    => 3.6E6,
  347                            'm'         => 2,
  348                            'kg'        => 1,
  349                            's'         => -2
  350                           },
  351 # POWER
  352 # W      -- Watt
  353 # kW     -- kilo Watt
  354 #
  355                  'W'  => {
  356                            'factor'    => 1,
  357                            'm'         => 2,
  358                            'kg'        => 1,
  359                            's'         => -3
  360                           },
  361                  'kW'  => {
  362                            'factor'    => 1000,
  363                            'm'         => 2,
  364                            'kg'        => 1,
  365                            's'         => -3
  366                           },
  367 # PRESSURE
  368 # Pa     -- Pascal
  369 # kPa    -- kilo Pascal
  370 # atm    -- atmosphere
  371                  'Pa'  => {
  372                            'factor'    => 1,
  373                            'm'         => -1,
  374                            'kg'        => 1,
  375                            's'         => -2
  376                           },
  377                 'kPa'  => {
  378                            'factor'    => 1000,
  379                            'm'         => -1,
  380                            'kg'        => 1,
  381                            's'         => -2
  382                           },
  383                 'atm'  => {
  384                            'factor'    => 1.01E5,
  385                            'm'         => -1,
  386                            'kg'        => 1,
  387                            's'         => -2
  388                           },
  389 
  390 );
  391 
  392 
  393 
  394 sub process_unit {
  395 
  396   my $string = shift;
  397     die ("UNIT ERROR: No units were defined.") unless defined($string);  #
  398   #split the string into numerator and denominator --- the separator is /
  399     my ($numerator,$denominator) = split( m{/}, $string );
  400 
  401 
  402 
  403   $denominator = "" unless defined($denominator);
  404   my %numerator_hash = process_term($numerator);
  405   my %denominator_hash =  process_term($denominator);
  406 
  407 
  408     my %unit_hash = %fundamental_units;
  409   my $u;
  410   foreach $u (keys %unit_hash) {
  411     if ( $u eq 'factor' ) {
  412       $unit_hash{$u} = $numerator_hash{$u}/$denominator_hash{$u};  # calculate the correction factor for the unit
  413     } else {
  414 
  415       $unit_hash{$u} = $numerator_hash{$u} - $denominator_hash{$u}; # calculate the power of the fundamental unit in the unit
  416     }
  417   }
  418   # return a unit hash.
  419   return(%unit_hash);
  420 }
  421 
  422 sub process_term {
  423   my $string = shift;
  424   my %unit_hash = %fundamental_units;
  425   if ($string) {
  426 
  427     #split the numerator or denominator into factors -- the separators are *
  428 
  429       my @factors = split(/\*/, $string);
  430 
  431     my $f;
  432     foreach $f (@factors) {
  433       my %factor_hash = process_factor($f);
  434 
  435       my $u;
  436       foreach $u (keys %unit_hash) {
  437         if ( $u eq 'factor' ) {
  438           $unit_hash{$u} = $unit_hash{$u} * $factor_hash{$u};  # calculate the correction factor for the unit
  439         } else {
  440 
  441           $unit_hash{$u} = $unit_hash{$u} + $factor_hash{$u}; # calculate the power of the fundamental unit in the unit
  442         }
  443       }
  444     }
  445   }
  446   #returns a unit hash.
  447   #print "process_term returns", %unit_hash, "\n";
  448   return(%unit_hash);
  449 }
  450 
  451 
  452 sub process_factor {
  453   my $string = shift;
  454   #split the factor into unit and powers
  455 
  456     my ($unit_name,$power) = split(/\^/, $string);
  457   $power = 1 unless defined($power);
  458   my %unit_hash = %fundamental_units;
  459 
  460   if ( defined( $known_units{$unit_name} )  ) {
  461     my %unit_name_hash = %{$known_units{$unit_name}};   # $reference_units contains all of the known units.
  462     my $u;
  463     foreach $u (keys %unit_hash) {
  464       if ( $u eq 'factor' ) {
  465         $unit_hash{$u} = $unit_name_hash{$u}**$power;  # calculate the correction factor for the unit
  466       } else {
  467         my $fundamental_unit = $unit_name_hash{$u};
  468         $fundamental_unit = 0 unless defined($fundamental_unit); # a fundamental unit which doesn't appear in the unit need not be defined explicitly
  469         $unit_hash{$u} = $fundamental_unit*$power; # calculate the power of the fundamental unit in the unit
  470       }
  471     }
  472   } else {
  473     die "UNIT ERROR Unrecognizable unit: |$unit_name|";
  474   }
  475   %unit_hash;
  476 }
  477 
  478 # This is the "exported" subroutine.  Use this to evaluate the units given in an answer.
  479 sub evaluate_units {
  480   my $unit = shift;
  481   my %output =  eval(q{process_unit( $unit)});
  482   %output = %fundamental_units if $@;  # this is what you get if there is an error.
  483   $output{'ERROR'}=$@ if $@;
  484   %output;
  485 }
  486 #################

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9