Arithmetic Operations

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 Operations on Multiple Values

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

Arithmetic Operations and Types

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.

Important

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.

Precedence of Arithmetic Operators

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

Addition, subtraction, and multiplication are straightforward. Table 16-3 shows some examples.

Table 16-3. Examples of arithmetic expressions

Example

Value

Value type

5 + 3

8

xs:integer

5 + 3.0

8

xs:decimal

5 + 3.0E0

8

xs:double

5 * 3

15

xs:integer

2 + 3 * 5

17

xs:integer

(2 + 3) * 5

25

xs:integer

− 3 + 5

2

xs:integer

( ) + 3

( )

N/A

doc("prices.xml")//prod[1]/price+5

34.99

xs:decimal

doc("prices.xml")//prod[1]/price-5

( )

N/A

doc("prices.xml")//prod[1]/price - 5

24.99

xs:decimal

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.[*]

Division

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

14 div 4

3.5

xs:double

14 idiv 4

3

xs:integer

−14 idiv 4

−3

xs:integer

14.0 div 3.5

4.0

xs:decimal

14.0 idiv 3.5

4

xs:integer

( ) div 3

( )

N/A

14 div 0

Error (division by zero)

N/A

xs:float("14") div 0

INF

xs:float

xs:double("INF") div 2

INF

xs:double

xs:float("NaN") div 2

NaN

xs:float

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.

Modulus (Remainder)

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

14 mod 4

2

xs:integer

−14 mod 4

−2

xs:integer

14 mod −4

2

xs:integer

14.9 mod 2.1

0.2

xs:decimal

14.5E1 mod 2E1

5

xs:double

xs:float("14") mod 0

NaN

xs:float

xs:double("INF") mod 2

NaN

xs:double

14 mod ( )

( )

N/A

14 mod xs:double("INF")

14

xs:double

Special rules, depicted in Table 16-6, apply when one of the operands is INF, -INF, or 0.

Table 16-6. Results for the mod operator

Divisor

Dividend

INF or -INF

Finite number

0 or −0

[a]

INF or -INF

NaN

The dividend

The dividend

Finite number

NaN

The remainder

0

0 or −0

NaN

NaN [a]

NaN [a]

[a] Or, if the operands are of type xs:decimal or xs:integer, a "division by zero" error is raised.



[*] The space after the dash is technically unnecessary since a name cannot start with a hyphen, but it looks cleaner.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.179.220