[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 193 - (download) (as text) (annotate)
Sat Sep 8 04:49:44 2001 UTC (18 years, 3 months ago) by gage
File size: 15982 byte(s)
Fixed a bug which prevented the unit mol from working.

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9