The following typical arithmetic operations can be performed on numeric values:
Addition and subtraction using the plus (+) and the minus (−) sign
Negation of a single value using the minus sign (−)
Multiplication using the *
operator
Division using the div
operator
Integer division (with results truncated) using the idiv
operator
Modulus (the remainder of a division) using the mod
operator
Some of these arithmetic operators can be used on date and time types in addition to numeric types. Date/time arithmetic is described in Chapter 19.
If the value NaN
is involved in an arithmetic operation (and the other operand is not the empty sequence), the result is always NaN
. If the empty sequence is used in an arithmetic operation, the result is always the empty sequence. It is important to understand that the empty sequence is different from zero. For example, $product/price - $product/discount
is equal to the empty sequence (not the value of $product/price
) if there is no element that matches the $product/discount
path.
Arithmetic operators cannot accept a sequence of more than one value as one of their operands. For example:
doc("prices.xml")//price * 2
will raise a type error because more than one price
element is returned by the path expression. To perform an arithmetic operation on a sequence of values, you can put parentheses around the arithmetic operation, as in:
doc("prices.xml")//(price * 2)
which will perform the operation on each price element individually and return a sequence of doubled price values. You could get the same results using a FLWOR, as in:
for $aPrice in doc("prices.xml")//price return $aPrice * 2
When an operation is performed on two values that are the same type, the result is also a value of that type. For example, adding two xs:integer
values results in an xs:integer
. However, if an operation is performed on values of two different numeric types, one value is promoted to the type of the other value. For example, adding an xs:decimal
to an xs:float
results in an xs:float
. This is true for all arithmetic operations except division of two xs:integer
values, which results in an xs:decimal
, and integer division, which always results in an x:integer
.
If an untyped value is used in an arithmetic operation, it is automatically cast to xs:double
. For example, when adding the xs:integer 2
to the untyped value 3
, the untyped value is cast to xs:double
, and the result is the xs:double
value 5
. All nonnumeric types must be explicitly cast to a numeric type before being used in an arithmetic operation.
Atomization occurs on the operands of arithmetic expressions. This means that the operations can be performed on nodes that contain numeric values as well as numeric atomic values themselves. For example, an arithmetic expression might be ($price * 2)
if $price
represents the path to a single node that contains a numeric value. For more information on atomization, see "Atomization" in Chapter 11.
XQuery 1.0 and XPath 2.0 have three differences from XPath 1.0 regarding the way arithmetic operations are handled:
In XPath 1.0, the result of an arithmetic operation on the empty sequence is NaN
, not the empty sequence.
In XPath 1.0, if an arithmetic operation is attempted on a sequence of more than one value, the first value is used and the rest are discarded. In XQuery 1.0/XPath 2.0, this raises a type error.
In XPath 1.0, operands of all types are automatically converted to numbers. In XQuery 1.0/XPath 2.0, the operands must be untyped or numeric.
Multiplication and division take precedence over addition and subtraction, as is customary in mathematical expressions. For example, 2 + 3 * 5
is equal to 2 + (3 * 5)
, or 17
, rather than (2 + 3) * 5
, or 25
. The unary minus operator has precedence over all others. For example, − 3 + 5
is equal to 2
, not
− (3 + 5)
, or -−8
.
Multiplication and division operators (*, div
, idiv
, and mod
) have equal precedence and are evaluated from left to right. Likewise, addition and subtraction operators have equal precedence and are evaluated from left to right. When in doubt, it is a good practice to use parentheses to delimit expressions for the sake of clarity.
Addition, subtraction, and multiplication are straightforward. Table 16-3 shows some examples.
Table 16-3. Examples of arithmetic expressions
Example |
Value |
Value type |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generally, you are not required to put whitespace before or after arithmetic operators. For example, price+5
, with no spaces, is a valid expression meaning "the value of the price
child plus 5." However, there is a special rule for subtraction. Because the dash (-
) is a valid character in XML names, it is necessary to put whitespace after any valid XML name that precedes it. For example, price-5
is interpreted as a single name, so to subtract, you should use price - 5
instead.[*]
There are two division
operators: div
and idiv
. A slash (/) cannot be used to indicate division because the / operator is used to delimit steps in a path expression. The div
operator is used to perform division of the first operand (the dividend) by the second operand (the divisor). If both numbers being divided are xs:integer
-based values, the result is an xs:decimal
. Otherwise, normal type promotion rules apply, and the type of the result is the same as the type of the operands.
The idiv
operator is used to divide two numbers and obtain the integer portion of the division result. The operands can have any numeric type. If the result of the division is not an even integer, the decimal portion of the number is truncated rather than rounded. For example, (14 div 4)
is equal to 3.5
, but (14 idiv 4)
is equal to 3
.
Table 16-4 shows examples of the div
and idiv
operators.
Table 16-4. Examples of the div and idiv operators
Example |
Value |
Value type |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Error (division by zero) |
|
|
|
|
|
|
|
|
|
|
Attempting to divide by zero will raise an error when using the idiv
operator or when using the div
operator with values of type xs:integer
or xs:decimal
. Using the div
operator on values of type xs:float
or xs:double
will not raise an error; it will return NaN
(if the dividend is 0
), or INF
or -INF
.
The mod
operator is used to obtain the remainder after dividing the first operand (the dividend) by the second operand (the divisor). For example, (14 mod 4)
equals 2
. The sign of the result is the same as the sign of the first operand. Table 16-5 shows examples of the mod
operator.
Table 16-5. Examples of the mod operator
Example |
Value |
Value type |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Special rules, depicted in Table 16-6, apply when one of the operands is INF
, -INF
, or 0
.
[*] The space after the dash is technically unnecessary since a name cannot start with a hyphen, but it looks cleaner.
18.221.179.220