[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9. Arithmetic Functions

This chapter describes the Calc commands for doing simple calculations on numbers, such as addition, absolute value, and square roots. These commands work by removing the top one or two values from the stack, performing the desired operation, and pushing the result back onto the stack. If the operation cannot be performed, the result pushed is a formula instead of a number, such as `2/0' (because division by zero is illegal) or `sqrt(x)' (because the argument `x' is a formula).

Most of the commands described here can be invoked by a single keystroke. Some of the more obscure ones are two-letter sequences beginning with the f ("functions") prefix key.

See section 5.7 Numeric Prefix Arguments, for a discussion of the effect of numeric prefix arguments on commands in this chapter which do not otherwise interpret a prefix argument.

9.1 Basic Arithmetic  
9.2 Integer Truncation  
9.3 Complex Number Functions  
9.4 Conversions  
9.5 Date Arithmetic  
9.6 Financial Functions  
9.7 Binary Number Functions  

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1 Basic Arithmetic

The + (calc-plus) command adds two numbers. The numbers may be any of the standard Calc data types. The resulting sum is pushed back onto the stack.

If both arguments of + are vectors or matrices (of matching dimensions), the result is a vector or matrix sum. If one argument is a vector and the other a scalar (i.e., a non-vector), the scalar is added to each of the elements of the vector to form a new vector. If the scalar is not a number, the operation is left in symbolic form: Suppose you added `x' to the vector `[1,2]'. You may want the result `[1+x,2+x]', or you may plan to substitute a 2-vector for `x' in the future. Since the Calculator can't tell which interpretation you want, it makes the safest assumption. See section 11.8 Reducing and Mapping Vectors, for a way to add `x' to every element of a vector.

If either argument of + is a complex number, the result will in general be complex. If one argument is in rectangular form and the other polar, the current Polar Mode determines the form of the result. If Symbolic Mode is enabled, the sum may be left as a formula if the necessary conversions for polar addition are non-trivial.

If both arguments of + are HMS forms, the forms are added according to the usual conventions of hours-minutes-seconds notation. If one argument is an HMS form and the other is a number, that number is converted from degrees or radians (depending on the current Angular Mode) to HMS format and then the two HMS forms are added.

If one argument of + is a date form, the other can be either a real number, which advances the date by a certain number of days, or an HMS form, which advances the date by a certain amount of time. Subtracting two date forms yields the number of days between them. Adding two date forms is meaningless, but Calc interprets it as the subtraction of one date form and the negative of the other. (The negative of a date form can be understood by remembering that dates are stored as the number of days before or after Jan 1, 1 AD.)

If both arguments of + are error forms, the result is an error form with an appropriately computed standard deviation. If one argument is an error form and the other is a number, the number is taken to have zero error. Error forms may have symbolic formulas as their mean and/or error parts; adding these will produce a symbolic error form result. However, adding an error form to a plain symbolic formula (as in `(a +/- b) + c') will not work, for the same reasons just mentioned for vectors. Instead you must write `(a +/- b) + (c +/- 0)'.

If both arguments of + are modulo forms with equal values of M, or if one argument is a modulo form and the other a plain number, the result is a modulo form which represents the sum, modulo M, of the two values.

If both arguments of + are intervals, the result is an interval which describes all possible sums of the possible input values. If one argument is a plain number, it is treated as the interval `[x .. x]'.

If one argument of + is an infinity and the other is not, the result is that same infinity. If both arguments are infinite and in the same direction, the result is the same infinity, but if they are infinite in different directions the result is nan.

The - (calc-minus) command subtracts two values. The top number on the stack is subtracted from the one behind it, so that the computation 5 RET 2 - produces 3, not -3. All options available for + are available for - as well.

The * (calc-times) command multiplies two numbers. If one argument is a vector and the other a scalar, the scalar is multiplied by the elements of the vector to produce a new vector. If both arguments are vectors, the interpretation depends on the dimensions of the vectors: If both arguments are matrices, a matrix multiplication is done. If one argument is a matrix and the other a plain vector, the vector is interpreted as a row vector or column vector, whichever is dimensionally correct. If both arguments are plain vectors, the result is a single scalar number which is the dot product of the two vectors.

If one argument of * is an HMS form and the other a number, the HMS form is multiplied by that amount. It is an error to multiply two HMS forms together, or to attempt any multiplication involving date forms. Error forms, modulo forms, and intervals can be multiplied; see the comments for addition of those forms. When two error forms or intervals are multiplied they are considered to be statistically independent; thus, `[-2 .. 3] * [-2 .. 3]' is `[-6 .. 9]', whereas `[-2 .. 3] ^ 2' is `[0 .. 9]'.

The / (calc-divide) command divides two numbers. When dividing a scalar B by a square matrix A, the computation performed is B times the inverse of A. This also occurs if B is itself a vector or matrix, in which case the effect is to solve the set of linear equations represented by B. If B is a matrix with the same number of rows as A, or a plain vector (which is interpreted here as a column vector), then the equation A X = B is solved for the vector or matrix X. Otherwise, if B is a non-square matrix with the same number of columns as A, the equation X A = B is solved. If you wish a vector B to be interpreted as a row vector to be solved as X A = B, make it into a one-row matrix with C-u 1 v p first. To force a left-handed solution with a square matrix B, transpose A and B before dividing, then transpose the result.

HMS forms can be divided by real numbers or by other HMS forms. Error forms can be divided in any combination of ways. Modulo forms where both values and the modulo are integers can be divided to get an integer modulo form result. Intervals can be divided; dividing by an interval that encompasses zero or has zero as a limit will result in an infinite interval.

The ^ (calc-power) command raises a number to a power. If the power is an integer, an exact result is computed using repeated multiplications. For non-integer powers, Calc uses Newton's method or logarithms and exponentials. Square matrices can be raised to integer powers. If either argument is an error (or interval or modulo) form, the result is also an error (or interval or modulo) form.

If you press the I (inverse) key first, the I ^ command computes an Nth root: 125 RET 3 I ^ computes the number 5. (This is entirely equivalent to 125 RET 1:3 ^.)

The \ (calc-idiv) command divides two numbers on the stack to produce an integer result. It is equivalent to dividing with /, then rounding down with F (calc-floor), only a bit more convenient and efficient. Also, since it is an all-integer operation when the arguments are integers, it avoids problems that / F would have with floating-point roundoff.

The % (calc-mod) command performs a "modulo" (or "remainder") operation. Mathematically, `a%b = a - (a\b)*b', and is defined for all real numbers a and b (except b=0). For positive b, the result will always be between 0 (inclusive) and b (exclusive). Modulo does not work for HMS forms and error forms. If a is a modulo form, its modulo is changed to b, which must be positive real number.

The : (calc-fdiv) command [fdiv function in a formula] divides the two integers on the top of the stack to produce a fractional result. This is a convenient shorthand for enabling Fraction Mode (with m f) temporarily and using `/'. Note that during numeric entry the : key is interpreted as a fraction separator, so to divide 8 by 6 you would have to type 8 RET 6 RET :. (Of course, in this case, it would be much easier simply to enter the fraction directly as 8:6 RET!)

The n (calc-change-sign) command negates the number on the top of the stack. It works on numbers, vectors and matrices, HMS forms, date forms, error forms, intervals, and modulo forms.

The A (calc-abs) [abs] command computes the absolute value of a number. The result of abs is always a nonnegative real number: With a complex argument, it computes the complex magnitude. With a vector or matrix argument, it computes the Frobenius norm, i.e., the square root of the sum of the squares of the absolute values of the elements. The absolute value of an error form is defined by replacing the mean part with its absolute value and leaving the error part the same. The absolute value of a modulo form is undefined. The absolute value of an interval is defined in the obvious way.

The f A (calc-abssqr) [abssqr] command computes the absolute value squared of a number, vector or matrix, or error form.

The f s (calc-sign) [sign] command returns 1 if its argument is positive, -1 if its argument is negative, or 0 if its argument is zero. In algebraic form, you can also write `sign(a,x)' which evaluates to `x * sign(a)', i.e., either `x', `-x', or zero depending on the sign of `a'.

The & (calc-inv) [inv] command computes the reciprocal of a number, i.e., 1 / x. Operating on a square matrix, it computes the inverse of that matrix.

The Q (calc-sqrt) [sqrt] command computes the square root of a number. For a negative real argument, the result will be a complex number whose form is determined by the current Polar Mode.

The f h (calc-hypot) [hypot] command computes the square root of the sum of the squares of two numbers. That is, `hypot(a,b)' is the length of the hypotenuse of a right triangle with sides a and b. If the arguments are complex numbers, their squared magnitudes are used.

The f Q (calc-isqrt) [isqrt] command computes the integer square root of an integer. This is the true square root of the number, rounded down to an integer. For example, `isqrt(10)' produces 3. Note that, like \ [idiv], this uses exact integer arithmetic throughout to avoid roundoff problems. If the input is a floating-point number or other non-integer value, this is exactly the same as `floor(sqrt(x))'.

The f n (calc-min) [min] and f x (calc-max) [max] commands take the minimum or maximum of two real numbers, respectively. These commands also work on HMS forms, date forms, intervals, and infinities. (In algebraic expressions, these functions take any number of arguments and return the maximum or minimum among all the arguments.)

The f M (calc-mant-part) [mant] function extracts the "mantissa" part m of its floating-point argument; f X (calc-xpon-part) [xpon] extracts the "exponent" part e. The original number is equal to m * 10^e, where m is in the interval `[1.0 .. 10.0)' except that m=e=0 if the original number is zero. For integers and fractions, mant returns the number unchanged and xpon returns zero. The v u (calc-unpack) command can also be used to "unpack" a floating-point number; this produces an integer mantissa and exponent, with the constraint that the mantissa is not a multiple of ten (again except for the m=e=0 case).

The f S (calc-scale-float) [scf] function scales a number by a given power of ten. Thus, `scf(mant(x), xpon(x)) = x' for any real `x'. The second argument must be an integer, but the first may actually be any numeric value. For example, `scf(5,-2) = 0.05' or `1:20' depending on the current Fraction Mode.

The f [ (calc-decrement) [decr] and f ] (calc-increment) [incr] functions decrease or increase a number by one unit. For integers, the effect is obvious. For floating-point numbers, the change is by one unit in the last place. For example, incrementing `12.3456' when the current precision is 6 digits yields `12.3457'. If the current precision had been 8 digits, the result would have been `12.345601'. Incrementing `0.0' produces 10^-p, where p is the current precision. These operations are defined only on integers and floats. With numeric prefix arguments, they change the number by n units.

Note that incrementing followed by decrementing, or vice-versa, will almost but not quite always cancel out. Suppose the precision is 6 digits and the number `9.99999' is on the stack. Incrementing will produce `10.0000'; decrementing will produce `9.9999'. One digit has been dropped. This is an unavoidable consequence of the way floating-point numbers work.

Incrementing a date/time form adjusts it by a certain number of seconds. Incrementing a pure date form adjusts it by a certain number of days.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2 Integer Truncation

There are four commands for truncating a real number to an integer, differing mainly in their treatment of negative numbers. All of these commands have the property that if the argument is an integer, the result is the same integer. An integer-valued floating-point argument is converted to integer form.

If you press H (calc-hyperbolic) first, the result will be expressed as an integer-valued floating-point number.

The F (calc-floor) [floor or ffloor] command truncates a real number to the next lower integer, i.e., toward minus infinity. Thus 3.6 F produces 3, but _3.6 F produces -4.

The I F (calc-ceiling) [ceil or fceil] command truncates toward positive infinity. Thus 3.6 I F produces 4, and _3.6 I F produces -3.

The R (calc-round) [round or fround] command rounds to the nearest integer. When the fractional part is .5 exactly, this command rounds away from zero. (All other rounding in the Calculator uses this convention as well.) Thus 3.5 R produces 4 but 3.4 R produces 3; _3.5 R produces -4.

The I R (calc-trunc) [trunc or ftrunc] command truncates toward zero. In other words, it "chops off" everything after the decimal point. Thus 3.6 I R produces 3 and _3.6 I R produces -3.

These functions may not be applied meaningfully to error forms, but they do work for intervals. As a convenience, applying floor to a modulo form floors the value part of the form. Applied to a vector, these functions operate on all elements of the vector one by one. Applied to a date form, they operate on the internal numerical representation of dates, converting a date/time form into a pure date.

There are two more rounding functions which can only be entered in algebraic notation. The roundu function is like round except that it rounds up, toward plus infinity, when the fractional part is .5. This distinction matters only for negative arguments. Also, rounde rounds to an even number in the case of a tie, rounding up or down as necessary. For example, `rounde(3.5)' and `rounde(4.5)' both return 4, but `rounde(5.5)' returns 6. The advantage of round-to-even is that the net error due to rounding after a long calculation tends to cancel out to zero. An important subtle point here is that the number being fed to rounde will already have been rounded to the current precision before rounde begins. For example, `rounde(2.500001)' with a current precision of 6 will incorrectly, or at least surprisingly, yield 2 because the argument will first have been rounded down to 2.5 (which rounde sees as an exact tie between 2 and 3).

Each of these functions, when written in algebraic formulas, allows a second argument which specifies the number of digits after the decimal point to keep. For example, `round(123.4567, 2)' will produce the answer 123.46, and `round(123.4567, -1)' will produce 120 (i.e., the cutoff is one digit to the left of the decimal point). A second argument of zero is equivalent to no second argument at all.

To compute the fractional part of a number (i.e., the amount which, when added to `floor(N)', will produce N) just take N modulo 1 using the % command.

Note also the \ (integer quotient), f I (integer logarithm), and f Q (integer square root) commands, which are analogous to /, B, and Q, respectively, except that they take integer arguments and return the result rounded down to an integer.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3 Complex Number Functions

The J (calc-conj) [conj] command computes the complex conjugate of a number. For complex number a+bi, the complex conjugate is a-bi. If the argument is a real number, this command leaves it the same. If the argument is a vector or matrix, this command replaces each element by its complex conjugate.

The G (calc-argument) [arg] command computes the "argument" or polar angle of a complex number. For a number in polar notation, this is simply the second component of the pair `(r; theta)'. The result is expressed according to the current angular mode and will be in the range -180 degrees (exclusive) to +180 degrees (inclusive), or the equivalent range in radians.

The calc-imaginary command multiplies the number on the top of the stack by the imaginary number i = (0,1). This command is not normally bound to a key in Calc, but it is available on the IMAG button in Keypad Mode.

The f r (calc-re) [re] command replaces a complex number by its real part. This command has no effect on real numbers. (As an added convenience, re applied to a modulo form extracts the value part.)

The f i (calc-im) [im] command replaces a complex number by its imaginary part; real numbers are converted to zero. With a vector or matrix argument, these functions operate element-wise.

The v p (calc-pack) command can pack the top two numbers on the stack into a composite object such as a complex number. With a prefix argument of -1, it produces a rectangular complex number; with an argument of -2, it produces a polar complex number. (Also, see section 11.2 Building Vectors.)

The v u (calc-unpack) command takes the complex number (or other composite object) on the top of the stack and unpacks it into its separate components.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4 Conversions

The commands described in this section convert numbers from one form to another; they are two-key sequences beginning with the letter c.

The c f (calc-float) [pfloat] command converts the number on the top of the stack to floating-point form. For example, 23 is converted to 23.0, 3:2 is converted to 1.5, and 2.3 is left the same. If the value is a composite object such as a complex number or vector, each of the components is converted to floating-point. If the value is a formula, all numbers in the formula are converted to floating-point. Note that depending on the current floating-point precision, conversion to floating-point format may lose information.

As a special exception, integers which appear as powers or subscripts are not floated by c f. If you really want to float a power, you can use a j s command to select the power followed by c f. Because c f cannot examine the formula outside of the selection, it does not notice that the thing being floated is a power. See section 12.1 Selecting Sub-Formulas.

The normal c f command is "pervasive" in the sense that it applies to all numbers throughout the formula. The pfloat algebraic function never stays around in a formula; `pfloat(a + 1)' changes to `a + 1.0' as soon as it is evaluated.

With the Hyperbolic flag, H c f [float] operates only on the number or vector of numbers at the top level of its argument. Thus, `float(1)' is 1.0, but `float(a + 1)' is left unevaluated because its argument is not a number.

You should use H c f if you wish to guarantee that the final value, once all the variables have been assigned, is a float; you would use c f if you wish to do the conversion on the numbers that appear right now.

The c F (calc-fraction) [pfrac] command converts a floating-point number into a fractional approximation. By default, it produces a fraction whose decimal representation is the same as the input number, to within the current precision. You can also give a numeric prefix argument to specify a tolerance, either directly, or, if the prefix argument is zero, by using the number on top of the stack as the tolerance. If the tolerance is a positive integer, the fraction is correct to within that many significant figures. If the tolerance is a non-positive integer, it specifies how many digits fewer than the current precision to use. If the tolerance is a floating-point number, the fraction is correct to within that absolute amount.

The pfrac function is pervasive, like pfloat. There is also a non-pervasive version, H c F [frac], which is analogous to H c f discussed above.

The c d (calc-to-degrees) [deg] command converts a number into degrees form. The value on the top of the stack may be an HMS form (interpreted as degrees-minutes-seconds), or a real number which will be interpreted in radians regardless of the current angular mode.

The c r (calc-to-radians) [rad] command converts an HMS form or angle in degrees into an angle in radians.

The c h (calc-to-hms) [hms] command converts a real number, interpreted according to the current angular mode, to an HMS form describing the same angle. In algebraic notation, the hms function also accepts three arguments: `hms(h, m, s)'. (The three-argument version is independent of the current angular mode.)

The calc-from-hms command converts the HMS form on the top of the stack into a real number according to the current angular mode.

The c p (calc-polar) command converts the complex number on the top of the stack from polar to rectangular form, or from rectangular to polar form, whichever is appropriate. Real numbers are left the same. This command is equivalent to the rect or polar functions in algebraic formulas, depending on the direction of conversion. (It uses polar, except that if the argument is already a polar complex number, it uses rect instead. The I c p command always uses rect.)

The c c (calc-clean) [pclean] command "cleans" the number on the top of the stack. Floating point numbers are re-rounded according to the current precision. Polar numbers whose angular components have strayed from the -180 to +180 degree range are normalized. (Note that results will be undesirable if the current angular mode is different from the one under which the number was produced!) Integers and fractions are generally unaffected by this operation. Vectors and formulas are cleaned by cleaning each component number (i.e., pervasively).

If the simplification mode is set below the default level, it is raised to the default level for the purposes of this command. Thus, c c applies the default simplifications even if their automatic application is disabled. See section 8.5 Simplification Modes.

A numeric prefix argument to c c sets the floating-point precision to that value for the duration of the command. A positive prefix (of at least 3) sets the precision to the specified value; a negative or zero prefix decreases the precision by the specified amount.

The keystroke sequences c 0 through c 9 are equivalent to c c with the corresponding negative prefix argument. If roundoff errors have changed 2.0 into 1.999999, typing c 1 to clip off one decimal place often conveniently does the trick.

The c c command with a numeric prefix argument, and the c 0 through c 9 commands, also "clip" very small floating-point numbers to zero. If the exponent is less than or equal to the negative of the specified precision, the number is changed to 0.0. For example, if the current precision is 12, then c 2 changes the vector `[1e-8, 1e-9, 1e-10, 1e-11]' to `[1e-8, 1e-9, 0, 0]'. Numbers this small generally arise from roundoff noise.

If the numbers you are using really are legitimately this small, you should avoid using the c 0 through c 9 commands. (The plain c c command rounds to the current precision but does not clip small numbers.)

One more property of c 0 through c 9, and of c c with a prefix argument, is that integer-valued floats are converted to plain integers, so that c 1 on `[1., 1.5, 2., 2.5, 3.]' produces `[1, 1.5, 2, 2.5, 3]'. This is not done for huge numbers (`1e100' is technically an integer-valued float, but you wouldn't want it automatically converted to a 100-digit integer).

With the Hyperbolic flag, H c c and H c 0 through H c 9 operate non-pervasively [clean].

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5 Date Arithmetic

The commands described in this section perform various conversions and calculations involving date forms (see section 6.9 Date Forms). They use the t (for time/date) prefix key followed by shifted letters.

The simplest date arithmetic is done using the regular + and - commands. In particular, adding a number to a date form advances the date form by a certain number of days; adding an HMS form to a date form advances the date by a certain amount of time; and subtracting two date forms produces a difference measured in days. The commands described here provide additional, more specialized operations on dates.

Many of these commands accept a numeric prefix argument; if you give plain C-u as the prefix, these commands will instead take the additional argument from the top of the stack.

9.5.1 Date Conversions  
9.5.2 Date Functions  
9.5.4 Time Zones  
9.5.3 Business Days  

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.1 Date Conversions

The t D (calc-date) [date] command converts a date form into a number, measured in days since Jan 1, 1 AD. The result will be an integer if date is a pure date form, or a fraction or float if date is a date/time form. Or, if its argument is a number, it converts this number into a date form.

With a numeric prefix argument, t D takes that many objects (up to six) from the top of the stack and interprets them in one of the following ways:

The `date(year, month, day)' function builds a pure date form out of the specified year, month, and day, which must all be integers. Year is a year number, such as 1991 (not the same as 91!). Month must be an integer in the range 1 to 12; day must be in the range 1 to 31. If the specified month has fewer than 31 days and day is too large, the equivalent day in the following month will be used.

The `date(month, day)' function builds a pure date form using the current year, as determined by the real-time clock.

The `date(year, month, day, hms)' function builds a date/time form using an hms form.

The `date(year, month, day, hour, minute, second)' function builds a date/time form. hour should be an integer in the range 0 to 23; minute should be an integer in the range 0 to 59; second should be any real number in the range `[0 .. 60)'. The last two arguments default to zero if omitted.

The t J (calc-julian) [julian] command converts a date form into a Julian day count, which is the number of days since noon on Jan 1, 4713 BC. A pure date is converted to an integer Julian count representing noon of that day. A date/time form is converted to an exact floating-point Julian count, adjusted to interpret the date form in the current time zone but the Julian day count in Greenwich Mean Time. A numeric prefix argument allows you to specify the time zone; see section 9.5.4 Time Zones. Use a prefix of zero to suppress the time zone adjustment. Note that pure date forms are never time-zone adjusted.

This command can also do the opposite conversion, from a Julian day count (either an integer day, or a floating-point day and time in the GMT zone), into a pure date form or a date/time form in the current or specified time zone.

The t U (calc-unix-time) [unixtime] command converts a date form into a Unix time value, which is the number of seconds since midnight on Jan 1, 1970, or vice-versa. The numeric result will be an integer if the current precision is 12 or less; for higher precisions, the result may be a float with (precision-12) digits after the decimal. Just as for t J, the numeric time is interpreted in the GMT time zone and the date form is interpreted in the current or specified zone. Some systems use Unix-like numbering but with the local time zone; give a prefix of zero to suppress the adjustment if so.

The t C (calc-convert-time-zones) [tzconv] command converts a date form from one time zone to another. You are prompted for each time zone name in turn; you can answer with any suitable Calc time zone expression (see section 9.5.4 Time Zones). If you answer either prompt with a blank line, the local time zone is used for that prompt. You can also answer the first prompt with $ to take the two time zone names from the stack (and the date to be converted from the third stack level).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.2 Date Functions

The t N (calc-now) [now] command pushes the current date and time on the stack as a date form. The time is reported in terms of the specified time zone; with no numeric prefix argument, t N reports for the current time zone.

The t P (calc-date-part) command extracts one part of a date form. The prefix argument specifies the part; with no argument, this command prompts for a part code from 1 to 9. The various part codes are described in the following paragraphs.

The M-1 t P [year] function extracts the year number from a date form as an integer, e.g., 1991. This and the following functions will also accept a real number for an argument, which is interpreted as a standard Calc day number. Note that this function will never return zero, since the year 1 BC immediately precedes the year 1 AD.

The M-2 t P [month] function extracts the month number from a date form as an integer in the range 1 to 12.

The M-3 t P [day] function extracts the day number from a date form as an integer in the range 1 to 31.

The M-4 t P [hour] function extracts the hour from a date form as an integer in the range 0 (midnight) to 23. Note that 24-hour time is always used. This returns zero for a pure date form. This function (and the following two) also accept HMS forms as input.

The M-5 t P [minute] function extracts the minute from a date form as an integer in the range 0 to 59.

The M-6 t P [second] function extracts the second from a date form. If the current precision is 12 or less, the result is an integer in the range 0 to 59. For higher precisions, the result may instead be a floating-point number.

The M-7 t P [weekday] function extracts the weekday number from a date form as an integer in the range 0 (Sunday) to 6 (Saturday).

The M-8 t P [yearday] function extracts the day-of-year number from a date form as an integer in the range 1 (January 1) to 366 (December 31 of a leap year).

The M-9 t P [time] function extracts the time portion of a date form as an HMS form. This returns `0@ 0' 0"' for a pure date form.

The t M (calc-new-month) [newmonth] command computes a new date form that represents the first day of the month specified by the input date. The result is always a pure date form; only the year and month numbers of the input are retained. With a numeric prefix argument n in the range from 1 to 31, t M computes the nth day of the month. (If n is greater than the actual number of days in the month, or if n is zero, the last day of the month is used.)

The t Y (calc-new-year) [newyear] command computes a new pure date form that represents the first day of the year specified by the input. The month, day, and time of the input date form are lost. With a numeric prefix argument n in the range from 1 to 366, t Y computes the nth day of the year (366 is treated as 365 in non-leap years). A prefix argument of 0 computes the last day of the year (December 31). A negative prefix argument from -1 to -12 computes the first day of the nth month of the year.

The t W (calc-new-week) [newweek] command computes a new pure date form that represents the Sunday on or before the input date. With a numeric prefix argument, it can be made to use any day of the week as the starting day; the argument must be in the range from 0 (Sunday) to 6 (Saturday). This function always subtracts between 0 and 6 days from the input date.

Here's an example use of newweek: Find the date of the next Wednesday after a given date. Using M-3 t W or `newweek(d, 3)' will give you the preceding Wednesday, so `newweek(d+7, 3)' will give you the following Wednesday. A further look at the definition of newweek shows that if the input date is itself a Wednesday, this formula will return the Wednesday one week in the future. An exercise for the reader is to modify this formula to yield the same day if the input is already a Wednesday. Another interesting exercise is to preserve the time-of-day portion of the input (newweek resets the time to midnight; hint: how can newweek be defined in terms of the weekday function?).

The `pwday(date)' function (not on any key) computes the day-of-month number of the Sunday on or before date. With two arguments, `pwday(date, day)' computes the day number of the Sunday on or before day number day of the month specified by date. The day must be in the range from 7 to 31; if the day number is greater than the actual number of days in the month, the true number of days is used instead. Thus `pwday(date, 7)' finds the first Sunday of the month, and `pwday(date, 31)' finds the last Sunday of the month. With a third weekday argument, pwday can be made to look for any day of the week instead of Sunday.

The t I (calc-inc-month) [incmonth] command increases a date form by one month, or by an arbitrary number of months specified by a numeric prefix argument. The time portion, if any, of the date form stays the same. The day also stays the same, except that if the new month has fewer days the day number may be reduced to lie in the valid range. For example, `incmonth(<Jan 31, 1991>)' produces `<Feb 28, 1991>'. Because of this, t I t I and M-2 t I do not always give the same results (`<Mar 28, 1991>' versus `<Mar 31, 1991>' in this case).

The `incyear(date, step)' function increases a date form by the specified number of years, which may be any positive or negative integer. Note that `incyear(d, n)' is equivalent to `incmonth(d, 12*n)', but these do not have simple equivalents in terms of day arithmetic because months and years have varying lengths. If the step argument is omitted, 1 year is assumed. There is no keyboard command for this function; use C-u 12 t I instead.

There is no newday function at all because F [floor] serves this purpose. Similarly, instead of incday and incweek simply use d + n or d + 7 n.

See section 9.1 Basic Arithmetic, for the f ] [incr] command which can adjust a date/time form by a certain number of seconds.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.3 Business Days

Often time is measured in "business days" or "working days," where weekends and holidays are skipped. Calc's normal date arithmetic functions use calendar days, so that subtracting two consecutive Mondays will yield a difference of 7 days. By contrast, subtracting two consecutive Mondays would yield 5 business days (assuming two-day weekends and the absence of holidays).

The t + (calc-business-days-plus) [badd] and t - (calc-business-days-minus) [bsub] commands perform arithmetic using business days. For t +, one argument must be a date form and the other must be a real number (positive or negative). If the number is not an integer, then a certain amount of time is added as well as a number of days; for example, adding 0.5 business days to a time in Friday evening will produce a time in Monday morning. It is also possible to add an HMS form; adding `12@ 0' 0"' also adds half a business day. For t -, the arguments are either a date form and a number or HMS form, or two date forms, in which case the result is the number of business days between the two dates.

By default, Calc considers any day that is not a Saturday or Sunday to be a business day. You can define any number of additional holidays by editing the variable Holidays. (There is an s H convenience command for editing this variable.) Initially, Holidays contains the vector `[sat, sun]'. Entries in the Holidays vector may be any of the following kinds of objects:

If the Holidays vector is empty, then t + and t - will act just like + and - because there will then be no difference between business days and calendar days.

Calc expands the intervals and formulas you give into a complete list of holidays for internal use. This is done mainly to make sure it can detect multiple holidays. (For example, `<Jan 1, 1989>' is both New Year's Day and a Sunday, but Calc's algorithms take care to count it only once when figuring the number of holidays between two dates.)

Since the complete list of holidays for all the years from 1 to 2737 would be huge, Calc actually computes only the part of the list between the smallest and largest years that have been involved in business-day calculations so far. Normally, you won't have to worry about this. Keep in mind, however, that if you do one calculation for 1992, and another for 1792, even if both involve only a small range of years, Calc will still work out all the holidays that fall in that 200-year span.

If you add a (positive) number of days to a date form that falls on a weekend or holiday, the date form is treated as if it were the most recent business day. (Thus adding one business day to a Friday, Saturday, or Sunday will all yield the following Monday.) If you subtract a number of days from a weekend or holiday, the date is effectively on the following business day. (So subtracting one business day from Saturday, Sunday, or Monday yields the preceding Friday.) The difference between two dates one or both of which fall on holidays equals the number of actual business days between them. These conventions are consistent in the sense that, if you add n business days to any date, the difference between the result and the original date will come out to n business days. (It can't be completely consistent though; a subtraction followed by an addition might come out a bit differently, since t + is incapable of producing a date that falls on a weekend or holiday.)

There is a holiday function, not on any keys, that takes any date form and returns 1 if that date falls on a weekend or holiday, as defined in Holidays, or 0 if the date is a business day.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5.4 Time Zones

Time zones and daylight savings time are a complicated business. The conversions to and from Julian and Unix-style dates automatically compute the correct time zone and daylight savings adjustment to use, provided they can figure out this information. This section describes Calc's time zone adjustment algorithm in detail, in case you want to do conversions in different time zones or in case Calc's algorithms can't determine the right correction to use.

Adjustments for time zones and daylight savings time are done by t U, t J, t N, and t C, but not by any other commands. In particular, `<may 1 1991> - <apr 1 1991>' evaluates to exactly 30 days even though there is a daylight-savings transition in between. This is also true for Julian pure dates: `julian(<may 1 1991>) - julian(<apr 1 1991>)'. But Julian and Unix date/times will adjust for daylight savings time: `julian(<12am may 1 1991>) - julian(<12am apr 1 1991>)' evaluates to `29.95834' (that's 29 days and 23 hours) because one hour was lost when daylight savings commenced on April 7, 1991.

In brief, the idiom `julian(date1) - julian(date2)' computes the actual number of 24-hour periods between two dates, whereas `date1 - date2' computes the number of calendar days between two dates without taking daylight savings into account.

The calc-time-zone [tzone] command converts the time zone specified by its numeric prefix argument into a number of seconds difference from Greenwich mean time (GMT). If the argument is a number, the result is simply that value multiplied by 3600. Typical arguments for North America are 5 (Eastern) or 8 (Pacific). If Daylight Savings time is in effect, one hour should be subtracted from the normal difference.

If you give a prefix of plain C-u, calc-time-zone (like other date arithmetic commands that include a time zone argument) takes the zone argument from the top of the stack. (In the case of t J and t U, the normal argument is then taken from the second-to-top stack position.) This allows you to give a non-integer time zone adjustment. The time-zone argument can also be an HMS form, or it can be a variable which is a time zone name in upper- or lower-case. For example `tzone(PST) = tzone(8)' and `tzone(pdt) = tzone(7)' (for Pacific standard and daylight savings times, respectively).

North American and European time zone names are defined as follows; note that for each time zone there is one name for standard time, another for daylight savings time, and a third for "generalized" time in which the daylight savings adjustment is computed from context.

 9    8    7    6    5    4     3.5     0     -1      -2     -2

 8    7    6    5    4    3     2.5     -1    -2      -3     -3

9/8  8/7  7/6  6/5  5/4  4/3  3.5/2.5  0/-1 -1/-2   -2/-3  -2/-3

To define time zone names that do not appear in the above table, you must modify the Lisp variable math-tzone-names. This is a list of lists describing the different time zone names; its structure is best explained by an example. The three entries for Pacific Time look like this:

( ( "PST" 8 0 )    ; Name as an upper-case string, then standard
  ( "PDT" 8 -1 )   ; adjustment, then daylight savings adjustment.
  ( "PGT" 8 "PST" "PDT" ) )   ; Generalized time zone.

With no arguments, calc-time-zone or `tzone()' obtains an argument from the Calc variable TimeZone if a value has been stored for that variable. If not, Calc runs the Unix `date' command and looks for one of the above time zone names in the output; if this does not succeed, `tzone()' leaves itself unevaluated. The time zone name in the `date' output may be followed by a signed adjustment, e.g., `GMT+5' or `GMT+0500' which specifies a number of hours and minutes to be added to the base time zone. Calc stores the time zone it finds into TimeZone to speed later calls to `tzone()'.

The special time zone name local is equivalent to no argument, i.e., it uses the local time zone as obtained from the date command.

If the time zone name found is one of the standard or daylight savings zone names from the above table, and Calc's internal daylight savings algorithm says that time and zone are consistent (e.g., PDT accompanies a date that Calc's algorithm would also consider to be daylight savings, or PST accompanies a date that Calc would consider to be standard time), then Calc substitutes the corresponding generalized time zone (like PGT).

If your system does not have a suitable `date' command, you may wish to put a `(setq var-TimeZone ...)' in your Emacs initialization file to set the time zone. The easiest way to do this is to edit the TimeZone variable using Calc's s T command, then use the s p (calc-permanent-variable) command to save the value of TimeZone permanently.

The t J and t U commands with no numeric prefix arguments do the same thing as `tzone()'. If the current time zone is a generalized time zone, e.g., EGT, Calc examines the date being converted to tell whether to use standard or daylight savings time. But if the current time zone is explicit, e.g., EST or EDT, then that adjustment is used exactly and Calc's daylight savings algorithm is not consulted.

Some places don't follow the usual rules for daylight savings time. The state of Arizona, for example, does not observe daylight savings time. If you run Calc during the winter season in Arizona, the Unix date command will report MST time zone, which Calc will change to MGT. If you then convert a time that lies in the summer months, Calc will apply an incorrect daylight savings time adjustment. To avoid this, set your TimeZone variable explicitly to MST to force the use of standard, non-daylight-savings time.

By default Calc always considers daylight savings time to begin at 2 a.m. on the first Sunday of April, and to end at 2 a.m. on the last Sunday of October. This is the rule that has been in effect in North America since 1987. If you are in a country that uses different rules for computing daylight savings time, you have two choices: Write your own daylight savings hook, or control time zones explicitly by setting the TimeZone variable and/or always giving a time-zone argument for the conversion functions.

The Lisp variable math-daylight-savings-hook holds the name of a function that is used to compute the daylight savings adjustment for a given date. The default is math-std-daylight-savings, which computes an adjustment (either 0 or -1) using the North American rules given above.

The daylight savings hook function is called with four arguments: The date, as a floating-point number in standard Calc format; a six-element list of the date decomposed into year, month, day, hour, minute, and second, respectively; a string which contains the generalized time zone name in upper-case, e.g., "WEGT"; and a special adjustment to be applied to the hour value when converting into a generalized time zone (see below).

The Lisp function math-prev-weekday-in-month is useful for daylight savings computations. This is an internal version of the user-level pwday function described in the previous section. It takes four arguments: The floating-point date value, the corresponding six-element date list, the day-of-month number, and the weekday number (0-6).

The default daylight savings hook ignores the time zone name, but a more sophisticated hook could use different algorithms for different time zones. It would also be possible to use different algorithms depending on the year number, but the default hook always uses the algorithm for 1987 and later. Here is a listing of the default daylight savings hook:

(defun math-std-daylight-savings (date dt zone bump)
  (cond ((< (nth 1 dt) 4) 0)
        ((= (nth 1 dt) 4)
         (let ((sunday (math-prev-weekday-in-month date dt 7 0)))
           (cond ((< (nth 2 dt) sunday) 0)
                 ((= (nth 2 dt) sunday)
                  (if (>= (nth 3 dt) (+ 3 bump)) -1 0))
                 (t -1))))
        ((< (nth 1 dt) 10) -1)
        ((= (nth 1 dt) 10)
         (let ((sunday (math-prev-weekday-in-month date dt 31 0)))
           (cond ((< (nth 2 dt) sunday) -1)
                 ((= (nth 2 dt) sunday)
                  (if (>= (nth 3 dt) (+ 2 bump)) 0 -1))
                 (t 0))))
        (t 0))

The bump parameter is equal to zero when Calc is converting from a date form in a generalized time zone into a GMT date value. It is -1 when Calc is converting in the other direction. The adjustments shown above ensure that the conversion behaves correctly and reasonably around the 2 a.m. transition in each direction.

There is a "missing" hour between 2 a.m. and 3 a.m. at the beginning of daylight savings time; converting a date/time form that falls in this hour results in a time value for the following hour, from 3 a.m. to 4 a.m. At the end of daylight savings time, the hour from 1 a.m. to 2 a.m. repeats itself; converting a date/time form that falls in this hour results in a time value for the first manifestion of that time (not the one that occurs one hour later).

If math-daylight-savings-hook is nil, then the daylight savings adjustment is always taken to be zero.

In algebraic formulas, `tzone(zone, date)' computes the time zone adjustment for a given zone name at a given date. The date is ignored unless zone is a generalized time zone. If date is a date form, the daylight savings computation is applied to it as it appears. If date is a numeric date value, it is adjusted for the daylight-savings version of zone before being given to the daylight savings hook. This odd-sounding rule ensures that the daylight-savings computation is always done in local time, not in the GMT time that a numeric date is typically represented in.

The `dsadj(date, zone)' function computes the daylight savings adjustment that is appropriate for date in time zone zone. If zone is explicitly in or not in daylight savings time (e.g., PDT or PST) the date is ignored. If zone is a generalized time zone, the algorithms described above are used. If zone is omitted, the computation is done for the current time zone.

See section B. Reporting Bugs, for the address of Calc's author, if you should wish to contribute your improved versions of math-tzone-names and math-daylight-savings-hook to the Calc distribution.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6 Financial Functions

Calc's financial or business functions use the b prefix key followed by a shifted letter. (The b prefix followed by a lower-case letter is used for operations on binary numbers.)

Note that the rate and the number of intervals given to these functions must be on the same time scale, e.g., both months or both years. Mixing an annual interest rate with a time expressed in months will give you very wrong answers!

It is wise to compute these functions to a higher precision than you really need, just to make sure your answer is correct to the last penny; also, you may wish to check the definitions at the end of this section to make sure the functions have the meaning you expect.

9.6.1 Percentages  
9.6.2 Future Value  
9.6.3 Present Value  
9.6.4 Related Financial Functions  
9.6.5 Depreciation Functions  
9.6.6 Definitions  

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.1 Percentages

The M-% (calc-percent) command takes a percentage value, say 5.4, and converts it to an equivalent actual number. For example, 5.4 M-% enters 0.054 on the stack. (That's the META or ESC key combined with %.)

Actually, M-% creates a formula of the form `5.4%'. You can enter `5.4%' yourself during algebraic entry. The `%' operator simply means, "the preceding value divided by 100." The `%' operator has very high precedence, so that `1+8%' is interpreted as `1+(8%)', not as `(1+8)%'. (The `%' operator is just a postfix notation for the percent function, just like `20!' is the notation for `fact(20)', or twenty-factorial.)

The formula `5.4%' would normally evaluate immediately to 0.054, but the M-% command suppresses evaluation as it puts the formula onto the stack. However, the next Calc command that uses the formula `5.4%' will evaluate it as its first step. The net effect is that you get to look at `5.4%' on the stack, but Calc commands see it as `0.054', which is what they expect.

In particular, `5.4%' and `0.054' are suitable values for the rate arguments of the various financial functions, but the number `5.4' is probably not suitable--it represents a rate of 540 percent!

The key sequence M-% * effectively means "percent-of." For example, 68 RET 25 M-% * computes 17, which is 25% of 68 (and also 68% of 25, which comes out to the same thing).

The c % (calc-convert-percent) command converts the value on the top of the stack from numeric to percentage form. For example, if 0.08 is on the stack, c % converts it to `8%'. The quantity is the same, it's just represented differently. (Contrast this with M-%, which would convert this number to `0.08%'.) The = key is a convenient way to convert a formula like `8%' back to numeric form, 0.08.

To compute what percentage one quantity is of another quantity, use / c %. For example, 17 RET 68 / c % displays `25%'.

The b % (calc-percent-change) [relch] command calculates the percentage change from one number to another. For example, 40 RET 50 b % produces the answer `25%', since 50 is 25% larger than 40. A negative result represents a decrease: 50 RET 40 b % produces `-20%', since 40 is 20% smaller than 50. (The answers are different in magnitude because, in the first case, we're increasing by 25% of 40, but in the second case, we're decreasing by 20% of 50.) The effect of 40 RET 50 b % is to compute (50-40)/40, converting the answer to percentage form as if by c %.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.2 Future Value

The b F (calc-fin-fv) [fv] command computes the future value of an investment. It takes three arguments from the stack: `fv(rate, n, payment)'. If you give payments of payment every year for n years, and the money you have paid earns interest at rate per year, then this function tells you what your investment would be worth at the end of the period. (The actual interval doesn't have to be years, as long as n and rate are expressed in terms of the same intervals.) This function assumes payments occur at the end of each interval.

The I b F [fvb] command does the same computation, but assuming your payments are at the beginning of each interval. Suppose you plan to deposit $1000 per year in a savings account earning 5.4% interest, starting right now. How much will be in the account after five years? fvb(5.4%, 5, 1000) = 5870.73. Thus you will have earned $870 worth of interest over the years. Using the stack, this calculation would have been 5.4 M-% 5 RET 1000 I b F. Note that the rate is expressed as a number between 0 and 1, not as a percentage.

The H b F [fvl] command computes the future value of an initial lump sum investment. Suppose you could deposit those five thousand dollars in the bank right now; how much would they be worth in five years? fvl(5.4%, 5, 5000) = 6503.89.

The algebraic functions fv and fvb accept an optional fourth argument, which is used as an initial lump sum in the sense of fvl. In other words, fv(rate, n, payment, initial) = fv(rate, n, payment) + fvl(rate, n, initial).

To illustrate the relationships between these functions, we could do the fvb calculation "by hand" using fvl. The final balance will be the sum of the contributions of our five deposits at various times. The first deposit earns interest for five years: fvl(5.4%, 5, 1000) = 1300.78. The second deposit only earns interest for four years: fvl(5.4%, 4, 1000) = 1234.13. And so on down to the last deposit, which earns one year's interest: fvl(5.4%, 1, 1000) = 1054.00. The sum of these five values is, sure enough, $5870.73, just as was computed by fvb directly.

What does fv(5.4%, 5, 1000) = 5569.96 mean? The payments are now at the ends of the periods. The end of one year is the same as the beginning of the next, so what this really means is that we've lost the payment at year zero (which contributed $1300.78), but we're now counting the payment at year five (which, since it didn't have a chance to earn interest, counts as $1000). Indeed, 5569.96 = 5870.73 - 1300.78 + 1000 (give or take a bit of roundoff error).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.3 Present Value

The b P (calc-fin-pv) [pv] command computes the present value of an investment. Like fv, it takes three arguments: pv(rate, n, payment). It computes the present value of a series of regular payments. Suppose you have the chance to make an investment that will pay $2000 per year over the next four years; as you receive these payments you can put them in the bank at 9% interest. You want to know whether it is better to make the investment, or to keep the money in the bank where it earns 9% interest right from the start. The calculation pv(9%, 4, 2000) gives the result 6479.44. If your initial investment must be less than this, say, $6000, then the investment is worthwhile. But if you had to put up $7000, then it would be better just to leave it in the bank.

Here is the interpretation of the result of pv: You are trying to compare the return from the investment you are considering, which is fv(9%, 4, 2000) = 9146.26, with the return from leaving the money in the bank, which is fvl(9%, 4, x) where x is the amount of money you would have to put up in advance. The pv function finds the break-even point, x = 6479.44, at which fvl(9%, 4, 6479.44) is also equal to 9146.26. This is the largest amount you should be willing to invest.

The I b P [pvb] command solves the same problem, but with payments occurring at the beginning of each interval. It has the same relationship to fvb as pv has to fv. For example pvb(9%, 4, 2000) = 7062.59, a larger number than pv produced because we get to start earning interest on the return from our investment sooner.

The H b P [pvl] command computes the present value of an investment that will pay off in one lump sum at the end of the period. For example, if we get our $8000 all at the end of the four years, pvl(9%, 4, 8000) = 5667.40. This is much less than pv reported, because we don't earn any interest on the return from this investment. Note that pvl and fvl are simple inverses: fvl(9%, 4, 5667.40) = 8000.

You can give an optional fourth lump-sum argument to pv and pvb; this is handled in exactly the same way as the fourth argument for fv and fvb.

The b N (calc-fin-npv) [npv] command computes the net present value of a series of irregular investments. The first argument is the interest rate. The second argument is a vector which represents the expected return from the investment at the end of each interval. For example, if the rate represents a yearly interest rate, then the vector elements are the return from the first year, second year, and so on.

Thus, npv(9%, [2000,2000,2000,2000]) = pv(9%, 4, 2000) = 6479.44. Obviously this function is more interesting when the payments are not all the same!

The npv function can actually have two or more arguments. Multiple arguments are interpreted in the same way as for the vector statistical functions like vsum. See section 11.7.1 Single-Variable Statistics. Basically, if there are several payment arguments, each either a vector or a plain number, all these values are collected left-to-right into the complete list of payments. A numeric prefix argument on the b N command says how many payment values or vectors to take from the stack.

The I b N [npvb] command computes the net present value where payments occur at the beginning of each interval rather than at the end.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.4 Related Financial Functions

The functions in this section are basically inverses of the present value functions with respect to the various arguments.

The b M (calc-fin-pmt) [pmt] command computes the amount of periodic payment necessary to amortize a loan. Thus pmt(rate, n, amount) equals the value of payment such that pv(rate, n, payment) = amount.

The I b M [pmtb] command does the same computation but using pvb instead of pv. Like pv and pvb, these functions can also take a fourth argument which represents an initial lump-sum investment.

The H b M key just invokes the fvl function, which is the inverse of pvl. There is no explicit pmtl function.

The b # (calc-fin-nper) [nper] command computes the number of regular payments necessary to amortize a loan. Thus nper(rate, payment, amount) equals the value of n such that pv(rate, n, payment) = amount. If payment is too small ever to amortize a loan for amount at interest rate rate, the nper function is left in symbolic form.

The I b # [nperb] command does the same computation but using pvb instead of pv. You can give a fourth lump-sum argument to these functions, but the computation will be rather slow in the four-argument case.

The H b # [nperl] command does the same computation using pvl. By exchanging payment and amount you can also get the solution for fvl. For example, nperl(8%, 2000, 1000) = 9.006, so if you place $1000 in a bank account earning 8%, it will take nine years to grow to $2000.

The b T (calc-fin-rate) [rate] command computes the rate of return on an investment. This is also an inverse of pv: rate(n, payment, amount) computes the value of rate such that pv(rate, n, payment) = amount. The result is expressed as a formula like `6.3%'.

The I b T [rateb] and H b T [ratel] commands solve the analogous equations with pvb or pvl in place of pv. Also, rate and rateb can accept an optional fourth argument just like pv and pvb. To redo the above example from a different perspective, ratel(9, 2000, 1000) = 8.00597%, which says you will need an interest rate of 8% in order to double your account in nine years.

The b I (calc-fin-irr) [irr] command is the analogous function to rate but for net present value. Its argument is a vector of payments. Thus irr(payments) computes the rate such that npv(rate, payments) = 0; this rate is known as the internal rate of return.

The I b I [irrb] command computes the internal rate of return assuming payments occur at the beginning of each period.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.5 Depreciation Functions

The functions in this section calculate depreciation, which is the amount of value that a possession loses over time. These functions are characterized by three parameters: cost, the original cost of the asset; salvage, the value the asset will have at the end of its expected "useful life"; and life, the number of years (or other periods) of the expected useful life.

There are several methods for calculating depreciation that differ in the way they spread the depreciation over the lifetime of the asset.

The b S (calc-fin-sln) [sln] command computes the "straight-line" depreciation. In this method, the asset depreciates by the same amount every year (or period). For example, `sln(12000, 2000, 5)' returns 2000. The asset costs $12000 initially and will be worth $2000 after five years; it loses $2000 per year.

The b Y (calc-fin-syd) [syd] command computes the accelerated "sum-of-years'-digits" depreciation. Here the depreciation is higher during the early years of the asset's life. Since the depreciation is different each year, b Y takes a fourth period parameter which specifies which year is requested, from 1 to life. If period is outside this range, the syd function will return zero.

The b D (calc-fin-ddb) [ddb] command computes an accelerated depreciation using the double-declining balance method. It also takes a fourth period parameter.

For symmetry, the sln function will accept a period parameter as well, although it will ignore its value except that the return value will as usual be zero if period is out of range.

For example, pushing the vector [1,2,3,4,5] (perhaps with v x 5) and then mapping V M ' [sln(12000,2000,5,$), syd(12000,2000,5,$), ddb(12000,2000,5,$)] RET produces a matrix that allows us to compare the three depreciation methods:

[ [ 2000, 3333, 4800 ]
  [ 2000, 2667, 2880 ]
  [ 2000, 2000, 1728 ]
  [ 2000, 1333,  592 ]
  [ 2000,  667,   0  ] ]

(Values have been rounded to nearest integers in this figure.) We see that sln depreciates by the same amount each year, syd depreciates more at the beginning and less at the end, and ddb weights the depreciation even more toward the beginning.

Summing columns with V R : + yields [10000, 10000, 10000]; the total depreciation in any method is (by definition) the difference between the cost and the salvage value.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.6.6 Definitions

For your reference, here are the actual formulas used to compute Calc's financial functions.

Calc will not evaluate a financial function unless the rate or n argument is known. However, payment or amount can be a variable. Calc expands these functions according to the formulas below for symbolic arguments only when you use the a " (calc-expand-formula) command, or when taking derivatives or integrals or solving equations involving the functions.

These formulas are shown using the conventions of "Big" display mode (d B); for example, the formula for fv written linearly is `pmt * ((1 + rate)^n) - 1) / rate'.

                              (1 + rate)  - 1
fv(rate, n, pmt) =      pmt * ---------------

                              ((1 + rate)  - 1) (1 + rate)
fvb(rate, n, pmt) =     pmt * ----------------------------

fvl(rate, n, pmt) =     pmt * (1 + rate)

                              1 - (1 + rate)  
pv(rate, n, pmt) =      pmt * ----------------

                              (1 - (1 + rate)  ) (1 + rate)
pvb(rate, n, pmt) =     pmt * -----------------------------

pvl(rate, n, pmt) =     pmt * (1 + rate)

                                    -1               -2               -3
npv(rate, [a, b, c]) =  a*(1 + rate)   + b*(1 + rate)   + c*(1 + rate)

                                        -1               -2
npvb(rate, [a, b, c]) = a + b*(1 + rate)   + c*(1 + rate)

                        (amt - x * (1 + rate)  ) * rate
pmt(rate, n, amt, x) =  -------------------------------
                               1 - (1 + rate)

                        (amt - x * (1 + rate)  ) * rate
pmtb(rate, n, amt, x) = -------------------------------
                         (1 - (1 + rate)  ) (1 + rate)

                                   amt * rate
nper(rate, pmt, amt) =  - log(1 - ------------, 1 + rate)

                                    amt * rate
nperb(rate, pmt, amt) = - log(1 - ---------------, 1 + rate)
                                  pmt * (1 + rate)

nperl(rate, pmt, amt) = - log(---, 1 + rate)

ratel(n, pmt, amt) =    ------ - 1

                        cost - salv
sln(cost, salv, life) = -----------

                             (cost - salv) * (life - per + 1)
syd(cost, salv, life, per) = --------------------------------
                                  life * (life + 1) / 2

                             book * 2
ddb(cost, salv, life, per) = --------,  book = cost - depreciation so far

In pmt and pmtb, x=0 if omitted.

These functions accept any numeric objects, including error forms, intervals, and even (though not very usefully) complex numbers. The above formulas specify exactly the behavior of these functions with all sorts of inputs.

Note that if the first argument to the log in nper is negative, nper leaves itself in symbolic form rather than returning a (financially meaningless) complex number.

`rate(num, pmt, amt)' solves the equation `pv(rate, num, pmt) = amt' for `rate' using H a R (calc-find-root), with the interval `[.01% .. 100%]' for an initial guess. The rateb function is the same except that it uses pvb. Note that ratel can be solved directly; its formula is shown in the above list.

Similarly, `irr(pmts)' solves the equation `npv(rate, pmts) = 0' for `rate'.

If you give a fourth argument to nper or nperb, Calc will also use H a R to solve the equation using an initial guess interval of `[0 .. 100]'.

A fourth argument to fv simply sums the two components calculated from the above formulas for fv and fvl. The same is true of fvb, pv, and pvb.

The ddb function is computed iteratively; the "book" value starts out equal to cost, and decreases according to the above formula for the specified number of periods. If the book value would decrease below salvage, it only decreases to salvage and the depreciation is zero for all subsequent periods. The ddb function returns the amount the book value decreased in the specified period.

The Calc financial function names were borrowed mostly from Microsoft Excel and Borland's Quattro. The ratel function corresponds to `@CGR' in Borland's Reflex. The nper and nperl functions correspond to `@TERM' and `@CTERM' in Quattro, respectively. Beware that the Calc functions may take their arguments in a different order than the corresponding functions in your favorite spreadsheet.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.7 Binary Number Functions

The commands in this chapter all use two-letter sequences beginning with the b prefix.

The "binary" operations actually work regardless of the currently displayed radix, although their results make the most sense in a radix like 2, 8, or 16 (as obtained by the d 2, d 8, or d 6 commands, respectively). You may also wish to enable display of leading zeros with d z. See section 8.7.1 Radix Modes.

The Calculator maintains a current word size w, an arbitrary positive or negative integer. For a positive word size, all of the binary operations described here operate modulo 2^w. In particular, negative arguments are converted to positive integers modulo 2^w by all binary functions.

If the word size is negative, binary operations produce 2's complement integers from -(2^(-w-1)) to 2^(-w-1)-1 inclusive. Either mode accepts inputs in any range; the sign of w affects only the results produced.

The b c (calc-clip) [clip] command can be used to clip a number by reducing it modulo 2^w. The commands described in this chapter automatically clip their results to the current word size. Note that other operations like addition do not use the current word size, since integer addition generally is not "binary." (However, see section 8.5 Simplification Modes, calc-bin-simplify-mode.) For example, with a word size of 8 bits b c converts a number to the range 0 to 255; with a word size of -8 b c converts to the range -128 to 127.

The default word size is 32 bits. All operations except the shifts and rotates allow you to specify a different word size for that one operation by giving a numeric prefix argument: C-u 8 b c clips the top of stack to the range 0 to 255 regardless of the current word size. To set the word size permanently, use b w (calc-word-size). This command displays a prompt with the current word size; press RET immediately to keep this word size, or type a new word size at the prompt.

When the binary operations are written in symbolic form, they take an optional second (or third) word-size parameter. When a formula like `and(a,b)' is finally evaluated, the word size current at that time will be used, but when `and(a,b,-8)' is evaluated, a word size of -8 will always be used. A symbolic binary function will be left in symbolic form unless the all of its argument(s) are integers or integer-valued floats.

If either or both arguments are modulo forms for which M is a power of two, that power of two is taken as the word size unless a numeric prefix argument overrides it. The current word size is never consulted when modulo-power-of-two forms are involved.

The b a (calc-and) [and] command computes the bitwise AND of the two numbers on the top of the stack. In other words, for each of the w binary digits of the two numbers (pairwise), the corresponding bit of the result is 1 if and only if both input bits are 1: `and(2#1100, 2#1010) = 2#1000'.

The b o (calc-or) [or] command computes the bitwise inclusive OR of two numbers. A bit is 1 if either of the input bits, or both, are 1: `or(2#1100, 2#1010) = 2#1110'.

The b x (calc-xor) [xor] command computes the bitwise exclusive OR of two numbers. A bit is 1 if exactly one of the input bits is 1: `xor(2#1100, 2#1010) = 2#0110'.

The b d (calc-diff) [diff] command computes the bitwise difference of two numbers; this is defined by `diff(a,b) = and(a,not(b))', so that `diff(2#1100, 2#1010) = 2#0100'.

The b n (calc-not) [not] command computes the bitwise NOT of a number. A bit is 1 if the input bit is 0 and vice-versa.

The b l (calc-lshift-binary) [lsh] command shifts a number left by one bit, or by the number of bits specified in the numeric prefix argument. A negative prefix argument performs a logical right shift, in which zeros are shifted in on the left. In symbolic form, `lsh(a)' is short for `lsh(a,1)', which in turn is short for `lsh(a,n,w)'. Bits shifted "off the end," according to the current word size, are lost.

The H b l command also does a left shift, but it takes two arguments from the stack (the value to shift, and, at top-of-stack, the number of bits to shift). This version interprets the prefix argument just like the regular binary operations, i.e., as a word size. The Hyperbolic flag has a similar effect on the rest of the binary shift and rotate commands.

The b r (calc-rshift-binary) [rsh] command shifts a number right by one bit, or by the number of bits specified in the numeric prefix argument: `rsh(a,n) = lsh(a,-n)'.

The b L (calc-lshift-arith) [ash] command shifts a number left. It is analogous to lsh, except that if the shift is rightward (the prefix argument is negative), an arithmetic shift is performed as described below.

The b R (calc-rshift-arith) [rash] command performs an "arithmetic" shift to the right, in which the leftmost bit (according to the current word size) is duplicated rather than shifting in zeros. This corresponds to dividing by a power of two where the input is interpreted as a signed, twos-complement number. (The distinction between the `rsh' and `rash' operations is totally independent from whether the word size is positive or negative.) With a negative prefix argument, this performs a standard left shift.

The b t (calc-rotate-binary) [rot] command rotates a number one bit to the left. The leftmost bit (according to the current word size) is dropped off the left and shifted in on the right. With a numeric prefix argument, the number is rotated that many bits to the left or right.

See section 11.6 Set Operations using Vectors, for the b p and b u commands that pack and unpack binary integers into sets. (For example, b u unpacks the number `2#11001' to the set of bit-numbers `[0, 3, 4]'.) Type b u V # to count the number of "1" bits in a binary integer.

Another interesting use of the set representation of binary integers is to reverse the bits in, say, a 32-bit integer. Type b u to unpack; type 31 TAB - to replace each bit-number in the set with 31 minus that bit-number; type b p to pack the set back into a binary integer.

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by XEmacs Webmaster on October, 2 2007 using texi2html