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