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