[system] / trunk / pg / lib / Units.pm Repository: Repository Listing bbplugincoursesdistsnplrochestersystemwww

Annotation of /trunk/pg/lib/Units.pm

Revision 3576 - (view) (download) (as text)

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

 aubreyja at gmail dot com ViewVC Help Powered by ViewVC 1.0.9