Jump to content

Příručka:Syntaxe funkce analyzátoru výrazů

From mediawiki.org
This page is a translated version of the page Manual:Expr parser function syntax and the translation is 100% complete.
Kouzelná slova

Funkce #expr a #ifexpr rozšíření ParserFunctions v MediaWiki vyhodnocují matematické a booleovské výrazy – tedy výrazy obsahující čísla a booleovské hodnoty. Nefunguje s libovolnými řetězci, jako většina ostatních funkcí parseru .

Syntaxe funkce #expr je:

{{ #expr: expression }}

Mezery nejsou potřeba, s výjimkou mezer mezi dvěma sousedními slovy (u operátorů a konstant). Uvnitř čísel nejsou povoleny žádné oddělovače skupin, známé také jako decimal a oddělovače tisíců, (mezery, čárky, apostrofy). Jediný podporovaný oddělovač desetinných míst je tečka. A v současné době jsou jedinými podporovanými číslicemi ASCII desetinné číslice 0–9.

Ve výrazech vložených do šablon buďte opatrní při použití magických slov pro prvky data a času, například {{CURRENTHOUR}}, protože jejich návratová hodnota může být na přeložených stránkách formátována odlišně, což poškodí výrazy (místo toho použijte funkci parseru #time s příslušnými příznaky xn před každým formátovacím prvkem). Podobné chyby se vyskytnou i u některých dalších magických slov, která vracejí množství (ujistěte se, že jste zahrnuli příslušný příznak raw formatting).

Obecné

Technicky vzato je výraz řetězec představující stromovou strukturu s uzly dvojic typ/hodnota, s binárními operátory binární operátory v infixové notaci, jednoduchými operátory v polštině a koncovými uzly reprezentovanými čísly a konstantami. Písmena v operátorech a názvech konstant nerozlišují velká a malá písmena.

The ParserFunctions extension determines which operators and constants, and what numbers, are supported. Písmeno e ve vědeckém zápisu (např. "2e3" pro 2000) a znaménko čísla se považují za operátory, zatímco podporovaná literální čísla jsou čísla bez znaménka v běžném desítkovém formátu. Rozšíření také určuje prioritu operátorů a chybových zpráv a převádí všechna čísla jako doslovy na hodnoty s plovoucí desetinnou čárkou.

Pro zbytek implementace rozšíření používá funkce a operátory z PHP, takže jakékoli konverze typů a zvláštnosti určitých operátorů jsou vlastnostmi samotných těchto PHP funkcí a operátorů. Formát výsledků je také zcela určen PHP.

Jediné použité datové typy jsou datové typy PHP float (formát s plovoucí desetinnou čárkou s dvojitou přesností) a integer (64bitový celé číslo). 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 Manual:Representation of numbers in expr parser function ).

Je použit Dynamické typování. Koncové uzly jsou všechny typu float (jak již bylo zmíněno, čísla se převádějí na float; to platí i pro čísla s celočíselnou hodnotou a formátem). Datový typ výsledku operace závisí na operátoru, u některých operátorů na typu argumentu (argumentů) a v některých případech na jejich hodnotě (hodnotách). Pokud je podle těchto pravidel výsledek typu float, jakýkoli argument typu integer se před operací převede na float a výsledek se také zaokrouhlí na float:

  • {{numfh|(trunc2^trunc62+trunc512)-2^62}} → 0
  • {{numfh|(trunc2^trunc62+trunc512)+(trunc2^trunc62+trunc1535)}} → 9 223 372 036 854 776 000 (ca. 9.2e18) 1.0000000000000hex*2^63
  • {{numfh|2^63+2047}} → 9 223 372 036 854 778 000 (ca. 9.2e18) 1.0000000000001hex*2^63

Apart from that, a numerical value outside the range of type integer is converted to float, except in the case of trunc (and mod, which involves applying trunc to the arguments first).

V běžném desítkovém zápisu existuje 31 operátorů (kromě dvou synonym), dvě konstanty a čísla bez znaménka.

Operátory, čísla a konstanty

Since literal numbers are of type float, trunc is sometimes used in the examples to construct an integer-type argument, to demonstrate the result of an operator for this case.

Operátor Args Činnost PHP Datový typ Prec Příklady
(number) 0 číslo bez znaménka v běžném desítkovém zápisu (unární plus a mínus a e jsou považovány za operátory, viz jinde v této tabulce) plovoucí float n.a.
{{#expr:1234567890123456789}} 1.2345678901235E+18
{{#expr:123456789.0123456789}} 123456789.01235
+ 1 jednočlenný znak + (nic) stejné jako argument n.a.
{{#expr:+1}} 1
{{#expr:+-1}} -1
{{#expr:+trunc1}} 1
- 1 jednočlenný - znak (negace) - same as argument 10
{{#expr:-12}} -12
{{#expr:-trunc12}} -12
{{#expr:-trunc(-2^63)}} 9.2233720368548E+18
pi 0 konstanta π pi() float n.a.
{{#expr:pi}} 3.1415926535898
e as subexpression 0 constant e exp(1) float n.a.
{{#expr:e}} 2.718281828459
e between subexpressions 2 *10^ * pow (10,..) float unless the factor on the left is of type integer and the exponent is non-negative and of type integer 10
{{#expr:2e3}} 2000
{{#expr:-2.3e-4}} -0.00023
{{#expr:(trunc2)e(trunc-3)}} 0.002
{{#expr:(trunc2)e(trunc0)}} 2
{{#expr:(trunc2)e(trunc18)}} 2000000000000000000
{{#expr:(trunc2)e(trunc19)}} 2.0E+19
{{#expr:6e(5-2)e-2}} 60
{{#expr:1e.5}} 3.1622776601684

Špatně:

{{#expr:e4}} Expression error: Unexpected number.
exp 1 exponential function ex exp float 9
{{#expr:exp43}} 4.7278394682293E+18
{{#expr:exp trunc0}} 1
{{#expr:exp709}} 8.218407461555E+307
{{#expr:exp-744}} 9.8813129168249E-324

Compare:

{{#expr:e^43}} 4.7278394682293E+18
{{#expr:trunc exp43}} 4727839468229346304
ln 1 natural logarithm log float 9
{{#expr:ln2}} 0.69314718055995
{{#expr:ln trunc1}} 0
{{#expr:ln8.9e307}} 709.07967482591
{{#expr:ln.5e-323}} -744.44007192138

Hence, the common logarithm of e.g. 2:

{{#expr:ln2/ln10}} 0.30102999566398
abs 1 absolute value abs same as argument, but never negative 9
{{#expr:abs-2}} 2
{{#expr:abs trunc-2}} 2
{{#expr:abs trunc-2^63}} 9.2233720368548E+18
sqrt 1 square root sqrt float 9
{{#expr:sqrt 4}} 2
{{#expr:sqrt 2}} 1.4142135623731
{{#expr:sqrt 1e19}} 3162277660.1684

Negative arguments are not permitted:

{{#expr:sqrt-1}} In sqrt: Result is not a number.
trunc 1 truncation (int), i.e. type-casting to integer integer 9
{{#expr:trunc1.2}} 1
{{#expr:trunc1.8}} 1
{{#expr:trunc-1.2}} -1
{{#expr:trunc(-2^64+1e5)}} 98304
{{#expr:trunc(-2^63+1e5)}} -9223372036854675456
{{#expr:trunc(2^63)}} -9223372036854775808
{{#expr:trunc(2^63+1e5)}} -9223372036854675456
{{#expr:trunc(2^64+1e5)}} 98304
floor 1 floor function floor float 9
{{#expr:floor1.2}} 1
{{#expr:floor-1.2}} -2
{{#expr:floor trunc3}} 3
ceil 1 ceiling function ceil float 9
{{#expr:ceil1.2}} 2
{{#expr:ceil-1.2}} -1
{{#expr:ceil trunc3}} 3
sin 1 sine sin float 9
{{#expr:sin.1}} 0.099833416646828
{{#expr:sin trunc1}} 0.8414709848079

With an angle in degrees, e.g. 30°:

{{#expr:sin(30*pi/180)}} 0.5
cos 1 cosine cos float 9
{{#expr:cos.1}} 0.99500416527803
{{#expr:cos trunc1}} 0.54030230586814
tan 1 tangent tan float 9
{{#expr:tan.1}} 0.10033467208545
{{#expr:tan trunc1}} 1.5574077246549
asin 1 arcsine asin float 9
{{#expr:asin.1}} 0.10016742116156
{{#expr:asin trunc1}} 1.5707963267949
acos 1 arccosine acos float 9
{{#expr:acos.1}} 1.4706289056333
{{#expr:acos trunc1}} 0
{{#expr:2*acos 0}} 3.1415926535898
atan 1 arctangent atan float 9
{{#expr:atan.1}} 0.099668652491162
{{#expr:atan trunc1}} 0.78539816339745
{{#expr:4*atan 1}} 3.1415926535898
not 1 negation, logical NOT ! integer (1 or 0) 9
{{#expr:not0}} 1
{{#expr:not1}} 0
{{#expr:not2}} 0
{{#expr:not trunc1}} 0
^ 2 exponentiation (power) pow float unless the base is of type integer and the exponent is non-negative and of type integer 8
{{#expr:2^3}} 8
{{#expr:-2^3}} -8
{{#expr:-2^4}} 16
{{#expr:(trunc2)^(trunc-3)}} 0.125
{{#expr:(trunc2)^(trunc0)}} 1
{{#expr:(trunc2)^(trunc62)}} 4611686018427387904
{{#expr:(trunc2)^(trunc63)}} 9.2233720368548E+18
{{#expr:(-2)^1.2}} NAN
{{#expr:(-2)^.5}} NAN
* 2 multiplication * integer if both arguments are integer, otherwise float 7
{{#expr:2*3}} 6
{{#expr:(trunc2)*3}} 6
{{#expr:2*trunc3}} 6
{{#expr:(trunc2)*trunc3}} 6
{{#expr:(trunc1e10)*trunc1e9}} 1.0E+19
/ (also written div) 2 division (div is not integer division[1]) / float, unless both arguments are integer and the mathematical result is an integer 7
{{#expr:6/3}} 2
{{#expr:(trunc6)/3}} 2
{{#expr:2/trunc6}} 0.33333333333333
{{#expr:(trunc6)/trunc3}} 2
{{#expr:(trunc6)/trunc4}} 1.5
mod 2 modulo operation, remainder of division after truncating both operands to an integer.[1] % integer 7
{{#expr:30mod7}} 2
{{#expr:-30mod7}} -2
{{#expr:30mod-7}} 2
{{#expr:-30mod-7}} -2
{{#expr:30.5mod7.9}} 2

May give unexpected results for some values of the second argument (see this section):

{{#expr:123mod2^64}} Division by zero.
fmod 2 modulo operation, floating point. Returns first argument after subtracting an integer multiple of the second argument. fmod float 7
{{#expr:5.7fmod1.3}} 0.5
{{#expr:99.9fmod60}} 39.9
{{#expr:2.99fmod1}} 0.99
{{#expr:-2.99fmod1}} -0.99
{{#expr:2.99fmod-1}} 0.99
{{#expr:-2.99fmod-1}} -0.99
+ 2 addition + integer if both arguments are integer, otherwise float 6
{{#expr:2+3}} 5
{{#expr:(trunc2)+3}} 5
{{#expr:2+trunc3}} 5
{{#expr:(trunc2)+trunc3}} 5
{{#expr:(trunc7e18)+trunc4e18}} 1.1E+19
- 2 subtraction - integer if both arguments are integer, otherwise float 6
{{#expr:3-2}} 1
{{#expr:(trunc3)-2}} 1
{{#expr:2-trunc2}} 0
{{#expr:(trunc3)-trunc2}} 1
{{#expr:(trunc-7e18)-trunc4e18}} -1.1E+19
round 2 rounds off the number on the left to a multiple of 1/10 raised to a power, with the exponent equal to the truncated value of the number given on the right round float 5
{{#expr:9.876round2}} 9.88
{{#expr:(trunc1234)round trunc-2}} 1200
{{#expr:4.5round0}} 5
{{#expr:-4.5round0}} -5
{{#expr:46.857round1.8}} 46.9
{{#expr:46.857round-1.8}} 50
= 2 equality (numerical incl. logical, not for strings) == integer (1 or 0) 4
{{#expr:3.0=3}} 1
{{#expr:3.1=3}} 0
{{#expr:3.0=trunc3}} 1
{{#expr:3.1=trunc3}} 0
{{#expr:1e16=trunc(1e16)}} 1
{{#expr:1e16=trunc(1e16)+trunc1}} 1
{{#expr:trunc(1e16)=trunc(1e16)+trunc1}} 0

wrong:

{{#expr:a=a}} Expression error: Unrecognized word "a".
<> (also written !=) 2 inequality, logical xor; not for strings (negation of =) != integer (1 or 0) 4
{{#expr:3<>3}} 0
{{#expr:3<>4}} 1
< 2 less than (not for ordering of strings) < integer (1 or 0) 4
{{#expr:3<3}} 0
{{#expr:3<4}} 1
{{#expr:2.9<3}} 1
{{#expr:3.0<3}} 0
{{#expr:2.9<trunc3}} 1
{{#expr:3.0<trunc3}} 0
{{#expr:1e16<trunc(1e16)+trunc1}} 0

Wrong:

{{#expr:a<b}} Expression error: Unrecognized word "a".
> 2 greater than (same as <, with arguments reversed) > integer (1 or 0) 4
{{#expr:4>3}} 1
{{#expr:3>3}} 0
<= 2 less than or equal to (same as >=, with arguments reversed) <= integer (1 or 0) 4
{{#expr:3<=4}} 1
{{#expr:3<=3}} 1
>= 2 greater than or equal to (negation of <) >= integer (1 or 0) 4
{{#expr:4>=3}} 1
{{#expr:3>=3}} 1
and 2 logical AND && integer (1 or 0) 3
{{#expr:3and4}} 1
{{#expr:-3and0}} 0
{{#expr:0and4}} 0
{{#expr:0and0}} 0
or 2 logical OR || integer (1 or 0) 2
{{#expr:3or4}} 1
{{#expr:-3or0}} 1
{{#expr:0or4}} 1
{{#expr:0or0}} 0

The logical operators and, or, and not interpret an input value of 0 as false and any other number as true, and return 0 for a false result and 1 for true. These output values also apply to the relation operators; thus {{#expr: (2 < 3) + 1}} gives 2.

To use and, or, and not in #if, #ifeq, or #ifexist contexts, one can use 1 as then-text (true case) and 0 as else-text (false case), then combine the results with the logical operators provided by #expr or #ifexpr. Note that negation can also be achieved by subtracting the result from 1 (inside of #expr or #ifexpr) or by simply switching the then- and else-text(s) of #if #ifeq #ifexists or #ifexpr. Also, note that the construct {{#expr: {{#if:{{{a|}}}|1|0}} or {{#if:{{{b|}}}|1|0}} }} is equivalent to the simpler {{#if:{{{a|}}}{{{b|}}}|1|0}}}}.

Priorita je uvedena ve sloupci "Prec" výše, vyšší číslo znamená, že operátor je použit dříve. Examples (">" refers to going before, "~" means application from left to right):

  • e > floor, not, etc.: {{#expr:floor1.5e1}} → 15, {{#expr:not0e1}} → 1
  • floor > ^: {{#expr:floor1.5^2}} → 1
  • ^ > *: {{#expr:2*3^2}} → 18
  • * ~ / ~ mod: {{#expr:12/3*2}} → 8, {{#expr:111/3mod10}} → 7, {{#expr:358mod10*2}} → 16,
  • * > +, -: {{#expr:2+3*4}} → 14, {{#expr:2-3*4}} → -10
  • + ~ -: {{#expr:6-2+3}} → 7, {{#expr:-2+3}} → 1
  • +, - > round: {{#expr:1.234round2-1}} → 1.2
  • round > = etc.: {{#expr:1.23=1.234round2}} → 1
  • = etc. > and: {{#expr:1 and 2=1}} → 0
  • and > or: {{#expr:1 or 1 and 0}} → 1

In the case of equal precedence number, evaluation is from left to right:

  • {{#expr:12/2*3}} → 18
  • {{#expr:3^3^3}} → 19683

Parentheses can force a different precedence: {{#expr:(2+3)*4}} → 20

Blank spaces are good for readability but not needed for working properly, except between words (including "e"), and not allowed within numbers:

  • {{#expr:7mod3}} gives 1 [1]
  • {{#expr:7.5round0}} gives 8 [2]
  • {{#expr:0and1}} gives 0 [3]
  • {{#expr:0or not0}} gives 1 [4]
  • {{#expr:0ornot0}} gives Expression error: Unrecognized word "ornot". [5]
  • {{#expr:123 456}} gives Expression error: Unexpected number. [6]
  • {{#expr:not not3}} gives 1 [7]
  • {{#expr:notnot3}} gives Expression error: Unrecognized word "notnot". [8]
  • {{#expr:---2}} gives -2 [9]
  • {{#expr:-+-2}} gives 2 [10]
  • {{#expr:2*-3}} gives -6 [11]
  • {{#expr:-not-not-not0}} gives -1 [12]
  • {{#expr:2*/3}} gives Expression error: Unexpected / operator. [13]
  • {{#expr:sinln1.1}} gives Expression error: Unrecognized word "sinln". [14]
  • {{#expr:sin ln1.1}} gives 0.095165945236752 [15]

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 each side either nothing or an operator) is Euler's constant. An e with nothing or an operator on one side and a subexpression on the other gives an error message.

Rounding operators

See also Manual:Rounding numbers for some more examples

The following rounding operators are supported:

  • Symmetric with respect to 0 and non-strictly monotonic on each side of 0:
    • trunc
    • round
  • Otherwise related to 0 and periodic on each side of 0:
    • mod

Trunc

Trunc converts a float to an integer by cutting off the decimal part. For values in the range 2^63 ≤ x ≤ 2^64, it returns x - 2^64. Values larger than 2^64 returns 0, and values less than -2^63 returns -2^63.

See the below examples:

  • {{#expr:trunc(-2*2^63-2^12)}} → -4096
  • {{#expr:trunc(-2*2^63+2^12)}} → 4096
  • {{#expr:trunc(-1*2^63-2^12)}} → 9223372036854771712
  • {{#expr:trunc(-1*2^63+2^12)}} → -9223372036854771712
  • {{#expr:trunc(0*2^63-2^12)}} → -4096
  • {{#expr:trunc(0*2^63+2^12)}} → 4096
  • {{#expr:trunc(1*2^63-2^12)}} → 9223372036854771712
  • {{#expr:trunc(1*2^63+2^12)}} → -9223372036854771712
  • {{#expr:trunc(2*2^63-2^12)}} → -4096
  • {{#expr:trunc(2*2^63+2^12)}} → 4096
  • {{#expr:trunc(2^64+1024)}} → 0
  • {{#expr:trunc(3*2^63-2^12)}} → 9223372036854771712
  • {{#expr:trunc(3*2^63+2^12)}} → -9223372036854771712

Converting a number to an integer type ensures precise display without rounding to 14 decimal places.

x is truncated, x = trunc x, if it is an integer or a floating-point number representing an integer value.

The expression p mod 0 results in an error message when used in MediaWiki, not the PHP operator %:

  • {{#expr:-27mod0}}Division by zero.

In PHP, when using the % operator, if p % 0 is calculated and conditions are met where 0 < |q| < 1 and q >= 2^64, the result is an empty string.

  • {{formatnum:{{#expr:-123 mod .9}}}}Division by zero.
  • {{formatnum:{{#expr:-123 mod -.9}}}}Division by zero.
  • {{formatnum:{{#expr:-123 mod (2^64)}}}}Division by zero.
  • {{formatnum:{{#expr:-123 mod 1e20}}}} → −123
  • Compare:
    • {{formatnum:{{#expr:-123 mod (2^64-2048)}}}} → −123

Floor and ceil

When using floor or ceil with an integer, it's first converted to a floating-point number before the function is applied.

  • {{numf|floor (trunc1e17+trunc1)}} → 100 000 000 000 000 000
  • {{numf|ceil (trunc1e17+trunc1)}} → 100 000 000 000 000 000

Use Template:Floor and Template:Ceil to get in such a case the integer-type expression for the exact result:

  • {{numf|{{floortrunc1e17+trunc1}}}} → 100 000 000 000 000 000
  • {{numf|{{ceil|trunc1e17+trunc1}}}} → 100 000 000 000 000 000

To check whether the internal result of an expression x is mathematically an integer one can simply test "(x) = floor (x)", or similarly with ceil (not with trunc because for large floats we would get false negatives, and not with round0, because for odd numbers between 2^52 and 2^53, we would get false negatives).

Safety margins

To round an integer x down to the nearest multiple of 7, you can do the following:

  • 7*((x-3)/7 round 0)
  • 7*floor((x+.5)/7)
  • 7*ceil((x-6.5)/7)

To round x to the nearest multiple of 7, you can do the following:

  • 7*((x/7) round 0)
  • 7*floor((x+3.5)/7)
  • 7*ceil((x-3.5)/7)

In these cases, the sign of x doesn't matter, even for rounding, because the value is never exactly halfway between integers. All methods provide the same safety margin of 0.5 in x, or 1/14 after dividing by 7, to allow for rounding errors.

For any real value of x, the difference between the two problems is equivalent to a shift in x by 3.5. However, in this case with integer x values, the shift is 3.

Precedence

Additions before round:

  • {{#expr:1.234 + 1.234 round 1 + 1}} 2.47

Modulo and multiplication operations have equal precedence and they are evaluated from left-to-right:

  • {{#expr:3 * 4 mod 10 * 10}} 20

When using spaces in expressions with precedence, the layout can sometimes be confusing:

  • {{#expr:23+45 mod 10}} 28

Instead, you can write:

  • {{#expr:23 + 45 mod10}} 28

Or you can parenthesis:

  • {{#expr:23 + (45 mod 10)}} 28

Positional and named parameters

Positional parameters can be used in calculations inside a template.

For example, in w:Template:To USD/data/2018, the {{{1}}} positional parameter refers to the amount of local currency to convert to US dollars, and the second positional parameter specifies the country whose currency is being used. When Chinese currency is specified (CHN), the effective template code is:

{{#expr: ({{{1}}} / 6.62) round {{#ifeq: {{{round}}} | yes | 0 | 2 }} }}

Here {{{round}}} is an optional named parameter. If it is equal to "yes", then the converted value is displayed to the nearest US dollar. The default is rounding to the nearest penny.

Transitivity

For comparing a number of type float with one of type integer, the integer is converted to float. Therefore the operators =, <= and >= are not necessarily transitive with mixed types:

  • {{#expr:trunc1e16=1e16}} → 1
  • {{#expr:1e16=trunc1e16+trunc1}} → 1
  • {{#expr:trunc1e16=trunc1e16+trunc1}} → 0
  • {{#expr:trunc1e16>=1e16}} → 1
  • {{#expr:1e16>=trunc1e16+trunc1}} → 1
  • {{#expr:trunc1e16>=trunc1e16+trunc1}} → 0

Similarly, if a >= b and b = c, that does not necessarily imply a >= c:

  • {{#expr:trunc1e16>=1e16}} → 1
  • {{#expr:1e16=trunc1e16+trunc1}} → 1
  • {{#expr:trunc1e16>=trunc1e16+trunc1}} → 0

However, < and > are properly transitive.

Monotonicity

When dividing 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:

  • {{numf|(trunc1e18-trunc2)/trunc3}} → 333 333 333 333 333 300
  • {{numf|(trunc1e18-trunc1)/trunc3}} → 333 333 333 333 333 300
  • {{numf|trunc1e18/trunc3}} → 333 333 333 333 333 300

Numbers as input

Leading zeros are allowed, as well as a trailing decimal point (for an integer) and trailing zeros in a number with a decimal point.

  • "{{#expr: +01.20}}" gives "1.2" [16]
  • "{{#expr: 12.}}" gives "12" [17]

These equivalences apply also for #ifeq and #switch, see below.

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. Do not use group separators; a comma is not a recognized symbol for an expression, and an error for an unexpected number is returned if there is a space between two numeric values.

Thus a number can only consist of (following an optional leading sign):

  • one or more digits; or
  • zero or more digits, a decimal point, and zero or more digits.

Numbers in other scripts are not supported.

Examples:

  • "{{#expr:123}}" gives "123" [18]
  • "{{#expr:123.456}}" gives "123.456" [19]
  • "{{#expr:.456}}" gives "0.456" [20]
  • "{{#expr:0}}" gives "0" [21]

Also accepted:

  • "{{#expr: 123.}}" gives "123" [22]
  • "{{#expr:000123.4560}}" gives "123.456" [23]
  • "{{#expr:.}}" gives "0" [24]

With ignored part:

  • "{{#expr:123.456.789}}" gives "123.456" [25]

But wrong:

  • "{{#expr: 123,456}}" gives "Expression error: Unrecognized punctuation character ","." [26]
  • "{{#expr: 123 456}}" gives "Expression error: Unexpected number." [27]
  • "{{#expr:١٢٣}}" gives "Expression error: Unrecognized punctuation character "١"." [28]

Combinations with the operator e:

Float:

  • "{{#expr:2.3e-5}}" gives "2.3E-5" [29]
  • {{#expr:2e18}} → 2.0E+18

Integer type:

  • {{#expr:(trunc123456789012345)e trunc4}} → 1234567890123450000

Compare:

  • {{#expr:123456789012345e4}} → 1.2345678901235E+18
  • {{#expr:trunc123456789012345e4}} → 1234567890123450112
  • {{#expr:(trunc123456789012345)e4}} → 1.2345678901235E+18
  • "{{#expr: e5}}" gives "Expression error: Unexpected number." [30]
  • "{{#expr: e}}" gives "2.718281828459" [31]
  • "{{#expr: E}}" gives "2.718281828459" [32]

Commas can be removed as follows (obviously this is most useful when the value is provided by a template call, parser function, or some other magic word):

  • {{formatnum:1,2,,34.567,8|R}} → 1.2..34.567.8

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 800

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:

  • {{hex|0.00000000000000011102230246251566636831481088739149080825}}1.0000000000000hex*2^-53
  • {{hex|0.00000000000000011102230246251566636831481088739149080826}}1.0000000000001hex*2^-53
  • {{numf|2^-53}} → ,00000000000000011102230246251565<Expression error: Missing operand for <.
  • {{numf|2^-53+2^-105}} → ,00000000000000011102230246251568<Expression error: Missing operand for <.

Similarly:

  • {{numfh|4398046511104.00048828125}} → 4 398 046 511 104 (ca. 4.4e12) 1.0000000000000hex*2^42
  • {{numfh|4398046511104.00048828125000000000000000000000000000000000000000000000001}} → 4 398 046 511 104,001 (ca. 4.4e12) 1.0000000000001hex*2^42
  • 2^42+2^-10 = 4,398,046,511,104.000,976,562,5

Thus we see that the value halfway the two consecutive floats is rounded down in this case, while the other decimal fractions between the two floats are rounded to the nearest of the two.

Numbers as output

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, 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:

  • {{numfh|4.1e6}} → 4 099 999,9999999995 (ca. 4.1e6) 1.f47cfffffffffhex*2^21

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 decimal point only), but does not convert from or to scientific format:

  • {{formatnum:1234567.890123}} → 1 234 567,890123
  • {{formatnum:1234567.890123E16}} → 12 345 678 901 230 000 000 000

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×10Template:Valid.

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:

  • {{numf|trunc3^trunc39}} → 4 052 555 153 018 976 000
  • {{numf|trunc3^trunc40}} → 12 157 665 459 056 929 000
  • {{numf|1/7}} → ,14285714285714285

Negative zero

Although the literal "-0" (the unary minus applied to 0) gives 0, some operations give the float value "−0" (preserving commutativity of + and *):

Generating −0 with *, /, ceil, round:

  • {{#expr: -1*0}} → -0
  • {{#expr: (-1e-200)*1e-200}} → -0
  • {{#expr: -1/1e333}} → -0
  • {{#expr: 0/-1}} → -0
  • {{#expr: (-1e-200)/1e200}} → -0
  • {{#expr: (1e-200)/-1e200}} → -0
  • {{#expr: ceil(-.1)}} → -0
  • {{#expr: -.2round0}} → -0

Passing −0 on with unary +, binary + and -, * (and hence operator e), /, floor, ceil:

  • {{#expr: +(-1*0)}} → -0
  • {{#expr: (-1*0)+(-1*0)}} → -0
  • {{#expr: (-1*0)-0}} → -0
  • {{#expr: 1*(-1*0)}} → -0
    • {{#expr: (-1*0)e0}} → -0
  • {{#expr: (-1*0)/1}} → -0
  • {{#expr: floor(-1*0)}} → -0
  • {{#expr: ceil(-1*0)}} → -0

However:

  • {{#expr: -0}} → -0
  • {{#expr: -10^-401}} → -0

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 will remove the minus sign from a possible −0 but not affect any other result is the addition of 0. If an expression may be of type integer then one can add trunc0.

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

Type conversion

A float can be converted to type integer by operator trunc (however, note that for 2^63 <= x <= 2^64, we get x − 2^64, and for larger x we get 0; for x < −2^63 we get −2^63).

An expression of type integer can be converted to float by adding 0. Note that for integers greater than 2^53, this involves rounding.

Limitations and workarounds

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:

  • {{#expr:123mod(2^64-1)}}Division by zero.

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.

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.

Branching depending on an expression

The function #ifexpr produces one of two specified results, depending on the value of a boolean expression involving numbers and booleans (not strings). Examples:

  • {{#ifexpr: {{CURRENTDOW}} = 0 or {{CURRENTDOW}} = 6 | weekEND | weekDAY}} yields weekDAY because today is úterý and so "{{CURRENTDOW}}" is "2" [34].
  • {{#expr:2^10=1024}} → 1

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.

Again, equality is not transitive with mixed types:

  • {{#ifeq:12345678901234567|12345678901234568.0|1|0}} → 1
  • {{#ifeq:12345678901234568.0|12345678901234568|1|0}} → 1
  • {{#ifeq:12345678901234567|12345678901234568|1|0}} → 0
  • {{#ifeq:12345678901234567|12345678901234567e0|1|0}} → 1
  • {{#ifeq:12345678901234567e0|12345678901234568|1|0}} → 1
  • {{#ifeq:12345678901234567|12345678901234568|1|0}} → 0
  • {{num|trunc(2^62)-trunc1+trunc(2^62)}} → 9223372036854775807
  • {{#ifeq:9223372036854775700|9223372036854775900|1|0}} → 0
  • {{#ifeq:9223372036854775900|9223372036854775800|1|0}} → 0
  • {{#ifeq:9223372036854775700|9223372036854775800|1|0}} → 0

Comparisons

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:
    • {{#expr:1e23-.1e24}} → 0
    • {{#expr:1e23=.1e24}} → 1
    • {{#ifexpr:1e23=.1e24|1|0}} → 1
  • {{#ifeq:9034567890123456789|9034567890123456788|1|0}} → 0 (two numbers of type integer, therefore only true if exactly equal); compare:
  • {{#ifeq:9034567890123456700.0|9034567890123456800|1|0}} → 1 (due to the decimal point in one number, both are rounded to float before the comparison, so the comparison is cruder)

Error messages

The following examples show all known #expr and #ifexpr error messages. The error strings are all within <strong class="error"> elements.

  • Division by zero
    • "{{#expr:1/0}}" → "Division by zero." [35]
  • Missing operand
    • "{{#expr:2+}}" → "Expression error: Missing operand for +." [36]
    • "{{#expr:2-}}" → "Expression error: Missing operand for -." [37]
    • "{{#expr:2*}}" → "Expression error: Missing operand for *." [38]
    • "{{#expr:2/}}" → "Expression error: Missing operand for /." [39]
  • Unexpected number
    • "{{#expr:1 2}}" → "Expression error: Unexpected number." [40]
  • Unexpected word
    • "{{#expr:1 a}}" → "Expression error: Unrecognized word "a"." [41]
  • Unexpected operator
    • "{{#ifexpr:1/*2}}" → "Expression error: Unexpected * operator." [42]
    • "{{#ifexpr:1*/2}}" → "Expression error: Unexpected / operator." [43]
    • "{{#expr:>1}}" → "Expression error: Unexpected > operator." [44]
    • "{{#expr: 1 (2)}}" → "Expression error: Unexpected ( operator." [45]
  • Unexpected bracket
    • "{{#expr: (1}}" → "Expression error: Unclosed bracket." [46]
    • "{{#expr: 1)}}" → "Expression error: Unexpected closing bracket." [47]
  • Unrecognized punctuation
    • "{{#expr:{{{a}}}}}" → "Expression error: Unrecognized punctuation character "{"." [48]
    • "{{#expr:2*123,456}}" → "Expression error: Unrecognized punctuation character ","." [49]
    • "{{#ifexpr:3%2}}" → "Expression error: Unrecognized punctuation character "%"." [50]
  • Unrecognized word
    • "{{#ifexpr:abc}}" → "Expression error: Unrecognized word "abc"." [51]
    • "{{#expr:abc.def}}" → "Expression error: Unrecognized word "abc"." [52]
  • Result is not a number
    • "{{#expr:sqrt-1}}" → "In sqrt: Result is not a number." [53]
  • Invalid argument
    • "{{#expr:ln0}}" → "Invalid argument for ln: less than or equal to 0." [54]
    • "{{#expr:asin-22}}" → "Invalid argument for asin: less than -1 or greater than 1." [55]
  • Stack exhausted
    • "{{#expr: {{x|34|(1+(}} 1 {{x|34|))}} }}" → "Expression error: Stack exhausted."

Note that this last example uses Template:x, which generates multiple copies of a given string. However:

  • "{{#expr: {{x|33|(1+(}} 1 {{x|33|))}} }}" → "34"

Large numbers and infinity

  • {{#expr: {{x|102|1000*}} 18 }} → 1.8E+307
  • {{#expr: {{x|102|1000*}} 179 }} → 1.79E+308
  • {{#expr: {{x|102|1000*}} 180 }} → INF

On Wikimedia wikis this last example gives "INF", but depending on the operating system of the server it may also give, e.g., "1.#INF".

INF also appears when an intermediate result is out of range:

  • {{#expr:1e309/1e308}} → INF
  • {{#expr:1e200*1e200*1e-300}} → INF

but:

  • {{#expr:1e200*(1e200*1e-300)}} → 1.0E+100

Notice that an infinite result is not considered an error:

  • {{#iferror: {{#expr:1e200*1e200*1e-300}} | error}} → INF

Miscellaneous malformed expressions or markup

These are not errors, per se, but are probably not what was intended.

  • "#expr:3.4.5.6" → "3.4"
  • "{{{#expr:2*3}}}" → "{{{#expr:2*3}}}"   (triple braces are interpreted as a reference to an undefined parameter named "#expr:2*3")
  • "{{#expr:2*3}}}" → "6}"   (extra closing braces are interpreted as plain text)
  • "{{{#expr:2*3}}" → "{6"   (one extra opening brace is interpreted as plain text)
  • "{{#expr:2*3}" → "{{#expr:2*3}"   (too few opening or closing braces results in everything being interpreted as plain text)

Checking for a number

Check whether a string is a valid numeric expression:

  • {{#if:{{#ifexpr:3}}|0|1}} gives 1
  • {{#if:{{#ifexpr:3-2}}|0|1}} gives 1
  • {{#if:{{#ifexpr:3 2}}|0|1}} gives 0

Find the value represented by a string if it is a valid numeric expression, otherwise just return the string:

  • {{#iferror:{{#expr:3}}|3}} gives 3
  • {{#iferror:{{#expr:3-2}}|3-2}} gives 1
  • {{#iferror:{{#expr:3 2}}|3 2}} gives 3 2

Check whether a string is a number:

  • {{#ifeq:3|{{#expr:3}}|1|0}} gives 1
  • {{#ifeq:-3|{{#expr:-3}}|1|0}} gives 1
  • {{#ifeq:3.5|{{#expr:3.5}}|1|0}} gives 1
  • {{#ifeq:03|{{#expr:03}}|1|0}} gives 1
  • {{#ifeq:3-2|{{#expr:3-2}}|1|0}} gives 0
  • {{#ifeq:3 2|{{#expr:3 2}}|1|0}} gives 0

Minus sign

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.
hyphen-minus, typed directly as the character '-' (U+002D) "{{#expr:-12}}" "-12" [56]
hyphen-minus, typed as the numerical character reference &#x2D; "{{#expr:&#x2D;12}}" "Expression error: Unrecognized punctuation character "&"." [57]
hyphen-minus, typed as the numerical character reference &#45; "{{#expr:&#45;12}}" "Expression error: Unrecognized punctuation character "&"." [58]
minus sign, typed directly as the character '−' (U+2212) "{{#expr:−12}}" "-12" [59]
minus sign, typed as the numerical character reference &#x2212; "{{#expr:&#x2212;12}}" "Expression error: Unrecognized punctuation character "&"." [60]
minus sign, typed as the numerical character reference &#8722; "{{#expr:&#8722;12}}" "Expression error: Unrecognized punctuation character "&"." [61]
minus sign, typed as the symbolic character reference &minus; "{{#expr:&minus;12}}" "-12" [62]
figure dash, typed directly as the character '‒' (U+2012) "{{#expr:‒12}}" "Expression error: Unrecognized punctuation character "‒"." [63]
figure dash, typed as the numerical character reference &#x2012; "{{#expr:&#x2012;12}}" "Expression error: Unrecognized punctuation character "&"." [64]
figure dash, typed as the numerical character reference &#8210; "{{#expr:&#8210;12}}" "Expression error: Unrecognized punctuation character "&"." [65]
en dash, typed directly as the character '–' (U+2013) "{{#expr:–12}}" "Expression error: Unrecognized punctuation character "–"." [66]
en dash, typed as the numerical character reference &#x2013; "{{#expr:&#x2013;12}}" "Expression error: Unrecognized punctuation character "&"." [67]
en dash, typed as the numerical character reference &#8211; "{{#expr:&#8211;12}}" "Expression error: Unrecognized punctuation character "&"." [68]
en dash, typed as the symbolic character reference &ndash; "{{#expr:&ndash;12}}" "Expression error: Unrecognized punctuation character "&"." [69]

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.

Displaying numbers and numeric expressions

A point of consideration can also be the possibility to apply the rendered output to #expr or #ifexpr, or to input it without conversion into other calculation programs. This would require the following:

  • use digits, not words
  • as mentioned above, use the hyphen as minus sign
  • use *, <=, >=, and <>, not ×, ≤, ≥, or ≠
  • do not use thousands separators (however, some programs allow them)
  • use output like 6E23 or 6e23 rather than 6×10Template:Valid

Examples:

  • "{{#expr:three}}" gives "Expression error: Unrecognized word "three"." [70]
  • "{{#expr:2<3}}" gives "1" [71]
  • "{{#expr:2≤3}}" gives "Expression error: Unrecognized punctuation character "≤"." [72]
  • "{{#expr:2<=3}}" gives "1" [73]
  • "{{#expr:2>3}}" gives "0" [74]
  • "{{#expr:2≥3}}" gives "Expression error: Unrecognized punctuation character "≥"." [75]
  • "{{#expr:2>=3}}" gives "0" [76]
  • "{{#expr:2*3}}" gives "6" [77]
  • "{{#expr:2×3}}" gives "Expression error: Unrecognized punctuation character "×"." [78]
  • "{{#expr:2,300}}" gives "Expression error: Unrecognized punctuation character ","." [79]
  • "{{#expr:6E23}}" gives "6.0E+23" [80]

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}} }} }} = 2 075 966 (instead of 2075966).

See also

References

  1. 1.0 1.1 div and mod are different from all programming languages, see phab:T8068