Help:Calculation

The accuracy and format of numeric results varies with the server. Currently the results produced by Wikimedia servers seem to be uniform.

The functions #expr: and #ifexpr: of MediaWiki extension ParserFunctions evaluate numerical expressions, and also boolean expressions involving numbers and booleans (not strings). The syntax is

{{ #expr: expression }}

Spaces are not needed, except between words (for operators and constants). Inside numbers no grouping separators (spaces, commas, apostrophes) are allowed, the only decimal separator supported is the period (dot, full stop, excluding commas), and currently the only supported digits are the European decimal digits 0-9.

In calculation expressions embedded within templates, be careful when using magic words for date and time elements, such as {{CURRENTHOUR}} as their return value may be formatted differently on translated pages and will break expressions (instead, use the parser function #time with the appropriate xg flags before each formatting element). Similar errors will occur with some other magic words that return quantities (make sure you include the appropriate raw formatting flag).

The ParserFunctions software determines which operators and constants, and what numbers, are supported. The e in scientific notation and the sign of a number are treated as operators, the supported literal numbers are unsigned numbers in ordinary decimal format. The ParserFunctions software also determines the precedence of the operators and the error messages, and it converts all literal numbers to type float.

For the rest the ParserFunctions software just defines the operators in terms of PHP functions and operators, and any type conversions and pecularities of the operators are properties of these PHP functions and operators themselves. Also, the format of the result is entirely determined by PHP.

The data types are the PHP data types float (double precision floating-point format) and integer (64-bit integer). The range for type integer is from −263 = -9,223,372,036,854,775,808 through 263 − 1 = 9,223,372,036,854,775,807. Type float allows fractions and very large numbers, but only in the range ±253 = ±9,007,199,254,740,992 can all integer values be exactly represented in type float (see Help:Calculation accuracy).

Dynamic typing is applied. The end nodes are all of type float (as mentioned, numbers are converted to float; this applies even for numbers with an integer value and format). The data type of the result of an operation depends on the operator, and for some operators on the type(s) of the argument(s), and in some cases on their value(s). If according to these rules the result is of type float, any argument of type integer is converted to float before the operation, and the result is also rounded to float:

Logical operators return 1 for true and 0 for false, and interpret 0 as false and any other number as true. Thus {{#expr: (2 < 3) + 1}} gives 2 [1]. Note that "and" and "or" work with #expr and #ifexpr only; for use with #if, #ifeq, and #ifexist, use 1 as then-text and 0 as else-text, and combine results with "and" and "or" in an outer #expr or #ifexpr. Instead of {{ #expr: {{#if:{{{a}}}|1|0}} or {{#if:{{{b}}}|1|0}} }} we can also use {{#if:{{{a}}}{{{b}}}|1|0}}}}. For negation, simply subtract from 1 or interchange then- and else-part.

Precedence is indicated in the table, a higher number means that the operator is applied first. Examples (">" refers to going before, "~" means application from left to right):

For scientific notation e is treated as an operator. An e between subexpressions works just like *10^, except that together with the unary minus, it has the highest precedence, e.g. before a separate ^, and that the implicit 10 is of type integer, not float. An e as subexpression (i.e., with an each side either nothing or an operator) is Euler's constant. An e with on one side nothing or an operator and on the other side a subexpression gives an error message.

In division of numbers of type integer, a small change in the dividend can change the type of the result. Therefore, if the absolute value of the result is greater than 2^53, it is not always a monotonic function of the dividend:

The part of the expression representing a number is a sequence of digits and points; due to floatval a second point and any digits and points immediately after it are ignored, and do not give an error message. Group separators are not allowed: a comma is considered an unrecognised punctuation character:

Input of a number of type integer is not possible. A float can be converted to type integer with the function trunc. An integer with a value that is not a float value can be constructed, e.g. with Template:Trunc, where the number is given in two pieces:

{{numf|{{trunc|12345678|90123456789}}}} → 1,234,567,890,123,456,789

The smallest positive float can be written:

{{#expr:.5e-323}} → 4.9406564584125E-324

but we cannot use that output as input:

{{#expr:4.9406564584125E-324}} → 0

All digits are used to determine the float to which a number is rounded, as demonstrated in a borderline case:

As opposed to ParserFunctions, "plural" accepts points and commas in numbers and interprets them in a site-language-specific way (depending on $separatorTransformTable in Messagesxx.php); on this site:

(on e.g. the German and the Dutch sites reversed w.r.t. the result on English sites).

However, this can be used instead of #ifeq, #ifexpr or #switch only for distinguishing a few site-language-specific categories of numbers (for English: 1 and "not equal to 1"; for French ≤1 and >1; etc.). Also, since it is designed for linguistic distinction of singular and plural, in some languages the categories of numbers are numerically less useful.

The MediaWiki software simply passes on the literal result of the PHP computation, except that logical values are changed to 1 and 0. Therefore the format can depend on the server.

A number of type integer is displayed without rounding and in ordinary decimal notation:

{{#expr:trunc(2^52)}} → 4503599627370496

{{#expr:-trunc(2^52)}} → -4503599627370496

{{#expr:trunc1100000}} → 1100000

{{#expr:trunc1200000}} → 1200000

{{#expr:trunc1300000}} → 1300000

{{#expr:trunc4100000}} → 4100000

while a number of type double is rounded to 14 significant digits, while inconsistently displaying some numbers in scientific format. This is reportedly a bug in the Zend Engine which has been fixed [33], but on Wikimedia apparently not yet:

{{#expr:2^52}} → 4.5035996273705E+15

{{#expr:-(2^52)}} → -4.5035996273705E+15

{{#expr:1100000}} → 1100000

{{#expr:1200000}} → 1200000

{{#expr:1300000}} → 1300000

{{#expr:4100000}} → 4100000

{{#expr:1/7}} → 0.14285714285714

Note: Internally, the expression may be computed with more digits (typically 18 significant digits, for example on Wikimedia servers which are using IEEE 64-bit double in the implementation of PHP used by MediaWiki, but possibly more depending on the hardware architecture supported by PHP, which may have been itself compiled to use "long double" with an extended precision using 80- to 128-bit binary formats), so the formatted value returned by #expr will not exhibit some small differences.

If MediaWiki is installed on a server whose PHP engine was compiled for an architecture using different binary storage formats for its C/C++ datatype "double" (possibly with less precision than the IEEE 64-bit format), and possibly optimized for speed (the compiled C code or its linked-in mathematical libraries may then not use "strict" IEEE rounding modes for every floating point operation, but may keep some precision for intermediate results by not rounding them at each step, or could also compute results faster using internal values with less precision), you will get different results in PHP: MediaWiki will not be able to use the same precision (or the same range of magnitudes), and the results of calculations may vary between servers. When installing MediaWiki on a PHP server, make sure you look at PHP configuration options.

For example if the architecture supports fast floating points only with 32-bit format,s you'll get only 7 or 8 significant digits, and the 14 digits displayed by MediaWiki may exceed what the server can really compute. As well you may get unexpected "infinite" values or zero where another server could have returned accurate values).

For some representable round numbers, notably some multiples of 100,000, scientific notation is produced, which, if reused in an expression, is not even exactly equal to the original number:

Thus we may want to either compare two results of #expr (for equality up to 14 digits) or compare two expressions, such as 4100000 and 4000000+100000 (for exact equality); depending on context and intention, the negative result of the comparison of the result of expr with the exact number may be confusing.

The function formatnum adds commas (on the left of the point only), but does not convert from or to scientific format:

{{formatnum:1234567.890123}} → 1,234,567.890123

{{formatnum:1234567.890123E16}} → 1,234,567.890123E16

The number output is suitable for many other calculation programs, also the scientific notation. In that sense output like 6E23 is more convenient than 6×1023.

Template:Num displays a number with high accuracy (such that in the case of float the specific internal value is reconstructed when using the output as input), with the variant Template:Numf showing thousands separators:

Since 2011 the function #ifexpr takes both 0 and the float -0 as false:

{{#ifexpr:0|1|0}} → 0

{{#ifexpr:-1*0|1|0}} → 0

Also, as argument of a logical operator -0 is taken as false:

{{#expr:not(-1*0)}} → 1

{{#expr:(-1*0)and1}} → 0

{{#expr:(-1*0)or0}} → 0

If an expression of type float can have the value -0, then an operation that removes the minus sign from a possible -0, but does not affect any other result, is the addition of 0. If an expression may be of type integer then one can add trunc0.

The operator trunc gives the correct mathematical result of rounding toward 0 to an integer for integer-type numbers and for floats x inside the integer range: -2^63 <= x < 2^63. To also get the correct mathematical result for floats outside this range is simple, because these floats all have an integer value, so they can be left unchanged. Template:Trunc does this.

The operator mod gives strange errors for some fairly large values of the second argument:

The operator round with second argument 0 gives wrong results for odd numbers between 2^52 and 2^53, even though the exact results are representable as float. Also, the operator rounds integer-type numbers with an absolute value between 2^53 and 2^63 to float. Template:Round0 always gives the expression for the exact result, for subsequent use in an expression, or for display (with the accuracy of this depending on the accuracy of the display function or template only).

The operator floor rounds integer-type numbers with an absolute value between 2^53 and 2^63 to float, and not necessarily downward. Similarly the operator ceil rounds these numbers not necessarily upward. Template:Floor and Template:Ceil always give the expressions for the exact results, for subsequent use in an expression, or for display (with the accuracy of this, and the direction of rounding, depending on the display function or template only).

Note that rounding errors can affect a comparison, even if they are not visible in the displayed values: the internal values are compared. This applies even to large integers:

{{#expr:1024e20-1e23}} → 2.4E+21

{{#expr:1024e20-1e23=2.4e21}} → 0

Instead one may want to allow a relatively small difference that could be present due to rounding errors:

{{#expr:abs(1024e20-1e23-2.4e21)<1e8}} → 1

Again, for comparing a number of type float with one of type integer, the integer is converted to float. In this case the type is determined by the format of the number, e.g. 2 is an integer, but 2.0 and 2e0 are floats; also 12345678901234567890 is a float, because it is too large for an integer.

The functions #ifeq and #switch compare numbers and strings for equality using PHP operator ==, the same as the equality operator mentioned above, but now applied directly to the expanded wikitext of the arguments. For comparison as numbers no expressions (not even constants) are allowed, but in this case the unary plus and minus and the e of scientific notation are taken as part of the number, instead of as operators. Without e and decimal point the type is integer, otherwise it is float. As mentioned above, when an integer is compared with a float, the integer is converted to float first.

{{#ifeq:3|3.0|1|0}} → 1

{{#ifeq:3|03|1|0}} → 1

{{#ifeq:0.00003456|3.456E-05|1|0}} → 1

{{#ifeq:1e23|.1e24|1|0}} → 1 although rounding both numbers to float gives different internal numbers:

Only the hyphen-minus character or minus sign character, typed directly, work as a minus sign operator in expressions.

The HTML character references (by name or by numeric code point value) are not recognized when evaluating expressions: numerical character references are converted only when generating the final HTML document (after expansion of templates and parser functions)

Only a handful of character references by name are substituted early by MediaWiki, all others are interpreted only by the browser.

The other dash characters (such as the hyphen, the figure dash, en dash, em dash and others), though often similar visually, are not valid minus signs, but punctuation signs or typographical variants.

Also many other calculation programs require a hyphen. Therefore, in order to be able to copy rendered numbers and expressions to the edit box or input them through a copy operation into other calculation programs, displayed minus signs also need to be hyphens.

If the number is the result of a computation by MediaWiki and unsuitable for use in a new computation due to application of a formatting function such as #formatnum or a formatting template, one can copy the wikitext and apply the additional computation before the formatting. However, when templates are used, and copying is done to another wiki, these templates have to be copied too, or substituted.

If you want to calculate with Magic words and return group separated results you can use formatnum:{{formatnum: {{#expr: {{NUMBEROFPAGES:R}} - {{NUMBEROFFILES:R}} }} }} = 10,640,940 (instead of 10640940).