Next: Backwards Compatibility: ‘*’ and ‘-’, Previous: Complicated Unit Expressions, Up: Unit Expressions [Contents][Index]
Unit definitions are fixed once units
has finished reading the
units data file(s), but at run time you can assign unit expressions to
variables whose names begin with an underscore, using the syntax
_name = <unit expression>
This can help manage a long calculation by saving intermediate quantities as variables that you can use later. For example, to determine the shot-noise-limited signal-to-noise ratio (SNR) of an imaging system using a helium–neon laser, you could do
You have: _lambda = 632.8 nm # laser wavelength You have: _nu = c / _lambda # optical frequency You have: _photon_energy = h * _nu You have: _power = 550 uW You have: _photon_count = _power * 500 ns / _photon_energy You have: _snr = sqrt(_photon_count) You have: _snr You want: Definition: sqrt(_photon_count) = 29597.922
Except for beginning with an underscore, runtime variables follow the same naming rules as units. Because names beginning with ‘_’ are reserved for these variables and unit names cannot begin with ‘_’, runtime variables can never hide unit definitions. Runtime variables are undefined until you make an assignment to them, so if you give a name beginning with an underscore and no assignment has been made, you get an error message.
When you assign a unit expression to a runtime variable, units
checks the expression to determine whether it is valid, but the
resulting definition is stored as a text string that is not reduced to
primitive units. The text will be processed anew each time you use the
variable in a conversion or calculation; this means that if your
definition depends on other runtime variables (or the special variable
‘_’), the result of calculating with your variable will change if
any of those variables change. A dependence need not be direct.
Continuing the example of the laser above, suppose you have done the calculation as shown. You now wonder what happens if you switch to an argon laser:
You have: _lambda = 454.6 nm You have: _snr You want: Definition: sqrt(_photon_count) = 25086.651
If you then change the power:
You have: _power = 1 mW You have: _snr You want: Definition: sqrt(_photon_count) = 33826.834
Instead of having to reenter or edit a lengthy expression when you perform another calculation, you need only enter values that change; in this respect, runtime variables are similar to a spreadsheet.
The more times a variable appears in an expression that depends on it, the greater the benefit of having a calculation using that expression reflect changes to that variable. For example, the length of daylight—the time the Sun is above the horizon—at a given latitude and declination of the Sun is given by
where \(L\) is the day length, \(h\) is the Sun’s altitude (elevation angle), \(\phi\) is the location’s latitude, and \(\delta\) is the Sun’s declination (angle with the equatorial plane). The result above is in sidereal time; the length in solar time is obtained by multiplying by
siderealday / day
By convention, the Sun’s altitude at rise or set is \(-50^\prime\) to allow for atmospheric refraction and the semidiameter of its disk. At the summer solstice in the northern hemisphere, the Sun’s declination is approximately \(23.44^\circ\); to find the length of the longest day of the year for a latitude of \(55^\circ\), you could do
You have: _alt = -50 arcmin You have: _lat = 55 deg You have: _decl = 23.44 deg You have: _num = sin(_alt) - sin(_lat) sin(_decl) You have: _denom = cos(_lat) cos(_decl) You have: _sday = 2 (acos(_num / _denom) / circle) 24 hr You have: _day = _sday siderealday / day You have: _day You want: hms 17 hr + 19 min + 34.895151 sec
At the winter solstice, the Sun’s declination is approximately \(-23.44^\circ\), so you could calculate the length of the shortest day of the year using:
You have: _decl = -23.44 deg You have: _day You want: hms 7 hr + 8 min + 40.981084 sec
Latitude and declination each appear twice in the expression for
_day
; the result in the examples above is updated by changing
only the value of the declination.
It may seem easier—and less subject to error—to simply specify the
new value of _decl
as the negative of the current value (e.g.,
‘_decl = -_decl’). This doesn’t work; when you make an
assignment with the ‘=’ operator, the definition is stored as
entered, including possible dependencies on variables. But if you
attempt an assignment that is ultimately self-referential, the current
definition is retained, and you get an error message. For example,
You have: _decl = 23.44 deg You have: _decl = -_decl Circular unit definition
You can overcome this by using the ‘:=’ operator, which reduces the right hand side to primitive units before making the assignment, eliminating any dependencies on variables. Returning to the example above,
You have: _decl = 23.44 deg You have: _decl = -_decl Circular unit definition You have: _decl := -_decl You have: _decl You want: deg * -23.44 / -0.042662116
This works to much the same effect as if the assignment had been entered literally, e.g.,
You have: _decl = -23.44 deg
but the actual definition is in primitive units—in this case, radians:
You have: _decl = 23.44 deg You have: _decl := -_decl You have: _decl You want: Definition: -0.40910517666747087 radian = -0.40910518 radian
Definitions are text strings, and a redefinition using ‘:=’ is given with enough digits maintain the full precision of the current definition when converted back to a number; because it is a string, all digits are displayed when showing the definition, regardless of the numerical display precision, so you may see more digits than expected.
A runtime variable must be assigned before it can be used in an
assignment; in the first of the three examples above, giving the general
equation before the values for _alt
, _lat
, and _decl
had been assigned would result in an error message.
Next: Backwards Compatibility: ‘*’ and ‘-’, Previous: Complicated Unit Expressions, Up: Unit Expressions [Contents][Index]