[system] / trunk / webwork / system / courseScripts / Units.pm Repository: Repository Listing bbplugincoursesdistsnplrochestersystemwww

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

Thu Jun 14 17:08:51 2001 UTC (12 years 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
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,
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                           },
67                            'factor'    => 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,
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,
227                           },
228                 'kHz'  => {
229                            'factor'    => 1000*2*\$PI,  #1000*2pi,
230                            's'         => -1,
232                           },
233                 'MHz'  => {
234                            'factor'    => (10**6)*2*\$PI,  #10^6 * 2pi,
235                            's'         => -1,
237                           },
238                 'rev'  => {
239                       'factor'   => 2*\$PI,
241                       },
242                 'cycles'  => {
243                       'factor'   => 2*\$PI,
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 #################
```