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