Help:Calculation: Difference between revisions
genesis, port unchanged from Meta.wikimedia.org+cat w/{{Mediawiki} |
genesis, port unchanged from Wikipedia+cat w/{{Mediawiki} (for diff) |
||
| Line 1: | Line 1: | ||
:''The accuracy and format of numeric results varies with the server; even on a single page, while for any rendering there is consistency within the page, there is no consistency among renderings.'' | |||
: | The MediaWiki extension [[mw:ParserFunctions|ParserFunctions]] enables users to perform [[meta:Help:Calculation|calculations]], for simple arithmetic or for functions as on a [[scientific calculator]], with rounding, floor, [[logarithm]]s (<code>ln</code>), [[sine]], [[cosine]], or [[modulo]] (etc.), plus boolean comparisons with "=" or "<" or ">=" etc. | ||
The | The <tt>expr</tt> function evaluates numerical expressions, and also boolean expressions involving numbers and booleans (not strings). The syntax is | ||
:<nowiki>{{</nowiki> #expr: ''expression'' }} | :<nowiki>{{</nowiki> #expr: ''expression'' }} - Spaces are not required, but spaces/commas within numbers are not allowed. | ||
The supported operators (roughly in order of precedence) are: | |||
'''<tt>not</tt>''', '''<tt>^</tt>''', | |||
'''<tt>*</tt>''', '''<tt>/</tt>''', '''<tt>div</tt>''', '''<tt>mod</tt>''', | |||
'''<tt>+</tt>''', '''<tt>-</tt>''', | |||
'''<tt>round</tt>''', '''<tt>trunc</tt>''', | |||
'''<tt>=</tt>''', '''<tt><></tt>''', '''<tt>!=</tt>''', '''<tt><=</tt>''', '''<tt>>=</tt>''', | |||
'''<tt>and</tt>''', and | |||
'''<tt>or</tt>'''. Functions include: <code>'''abs( ), ceil( ), floor( ), [[natural logarithm|<font color=black>ln</font>]]( ), sin( ), cos( ), tan( )''',</code> etc. | |||
The precision supports 14-digit numbers ([[pi]]: {{#expr:pi}}, or longer on some servers) and E-notation ("1.54E17"), but [[truncation error]] can cause mismatches on comparisons of very large numbers or tiny decimals, so see below: "[[#Tactics for handling extreme numbers|Tactics for handling extreme numbers]]". | |||
== Operators == | |||
== Operators | |||
{| class="wikitable" | {| class="wikitable" | ||
! Operator | |||
! Operation | |||
! Examples | |||
|- | |- | ||
| | | none|| none | ||
| | | | ||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:123456789012345|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:1.23456789012345|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:.000001|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:.00000123456789012345|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:.123e4|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:123E-2|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:e|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:pi|gives={{!}}{{!}}}} | |||
|} | |} | ||
Wrong: | Wrong: | ||
{| class="wikitable" | {| class="wikitable" | ||
|{{ | |{{xpd0|#expr:e4|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! exp | |||
| [[ | | [[E_(mathematical_constant)|e]] to the specified power | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:exp1.2|gives={{!}}{{!}}}} | ||
{{ | |||
{{ | |||
|} | |} | ||
Compare: | Compare: | ||
{| class="wikitable" | {| class="wikitable" | ||
|{{ | |{{xpd0|#expr:e^1.2|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! ln | |||
| | | Natural logarithm | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:ln2|gives={{!}}{{!}}}} | ||
{{ | |||
{{ | |||
|} | |} | ||
Hence, the | Hence, the base ten logarithm of e.g. 2: | ||
{| class="wikitable" | {| class="wikitable" | ||
|{{ | |{{xpd0|#expr:ln2/ln10|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! abs | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:abs-1.2|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
|- | |- | ||
! trunc | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:trunc1.2|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:trunc-1.2|gives={{!}}{{!}}}} | |||
{{ | |||
{{ | |||
{{ | |||
|} | |} | ||
|- | |- | ||
! floor | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:floor1.2|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:floor-1.2|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! ceil | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:ceil1.2|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:ceil-1.2|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! sin | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:sin.1|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
With an angle in degrees, e.g. 30°: | With an angle in degrees, e.g. 30°: | ||
{| class="wikitable" | {| class="wikitable" | ||
|{{ | |{{xpd0|#expr:sin(30*pi/180)|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! cos | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:cos.1|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
|- | |- | ||
! tan | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:tan.1|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
|- | |- | ||
! asin | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:asin.1|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
|- | |- | ||
! acos | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:acos.1|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
|- | |- | ||
! atan | |||
| | | | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:atan.1|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
|- | |- | ||
| '''< | ! + | ||
| Unary '''<tt>+</tt>''' sign | |||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:+12|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:++12|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:+-12|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
| '''< | ! - | ||
| Unary '''<tt>-</tt>''' sign (negation) | |||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:-12|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:-+12|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:--12|gives={{!}}{{!}}}} | ||
{{ | |||
{{ | |||
|} | |} | ||
|- | |- | ||
! not | |||
| | | Unary NOT, logical NOT | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:not 0|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:not 1|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:not 2|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! ^ | |||
| | | Power | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:2^7|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:2^-7|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:(-2)^7|gives={{!}}{{!}}}} | ||
|- | |||
|{{xpd0|#expr:(-2)^8|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:2^1.2|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:2^.5|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:(-2)^1.2|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:(-2)^.5|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
! * | |||
| | | Multiplication | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:30*7|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:30*-7|gives={{!}}{{!}}}} | |||
{{ | |||
{{ | |||
|} | |} | ||
|- | |- | ||
| ''' | ! / | ||
|| Division, same as '''div''' | |||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:30/7|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:30/-7|gives={{!}}{{!}}}} | ||
{{ | |||
|} | |} | ||
|- | |- | ||
! [[w:en:Division_%28mathematics%29#Division_of_integers|div]] | |||
|| Division, same as '''/''',<br />not integer division | |||
| | | | ||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:30 div 7|gives={{!}}{{!}}}} (should be 4) | ||
{{ | |||
{{ | |||
|} | |} | ||
|- | |- | ||
! [[w:en:Modulo operation|mod]] | |||
|"Modulo", remainder of division after truncating both operands to an integer (PHP operator [http://www.php.net/manual/en/language.operators.arithmetic.php %]).<br /><br />Caveat, '''div''' and '''mod''' are different from all programming languages. This has been fixed (but needs to be committed), see [[bugzilla:6068]]. | |||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:30 mod 7|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:30 mod -7|gives={{!}}{{!}}}} | ||
{{ | |- | ||
{{ | |{{xpd0|#expr:-30 mod 7|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:-30 mod -7|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:-8 mod -3|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:-8 mod 2.9|gives={{!}}{{!}}}} (should be 2.6) | |||
|- | |||
|{{xpd0|#expr:-8 mod 3.2|gives={{!}}{{!}}}} (should be 1.6) | |||
|- | |||
|{{xpd0|#expr:8.9 mod 3|gives={{!}}{{!}}}} (should be 2.9) | |||
|} | |} | ||
|- | |- | ||
! <tt>+</tt> | |||
|| | || Addition | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
|{{xpd0|#expr:30 + 7|gives={{!}}{{!}}}} | |||
{{ | |||
{{ | |||
|} | |} | ||
|- | |||
! <tt>-</tt> | |||
|| Subtraction | |||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
|{{ | |{{xpd0|#expr:30 - 7|gives={{!}}{{!}}}} | ||
|} | |} | ||
|- | |- | ||
! round | |||
| | || Rounds off the number on the left to the power of 1/10 given on the right (PHP function [http://www.php.net/manual/en/function.round.php round]) | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:4.2857 round 3|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:4.2857 round 0|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:42857 round -2|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:4.5 round 0|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:-4.5 round 0|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
! = | |||
|| | || Equality (numerical incl. logical) | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
|{{xpd0|#expr:3{{=}}03.0|gives={{!}}{{!}}}} | |||
{{ | |||
{{ | |||
{{ | |||
{{ | |||
|} | |} | ||
|- | |||
! <> | |||
| Inequality, same as '''!=''' | |||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:3<>03.0|gives={{!}}{{!}}}} | ||
|- | |||
|{{xpd0|#expr:3<>4|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
| ''' | !| != | ||
|| Inequality, same as '''<>''', logical ''xor'' | |||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:3!{{=}}03.0|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:3!{{=}}4|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
! < | |||
| | || Less than | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:3<2|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:3<3|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:3<4|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
! > | |||
| | || Greater than | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:3>2|gives={{!}}{{!}}}} | ||
{{ | |- | ||
|{{xpd0|#expr:3>3|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:3>4|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
! <= | |||
| | | Less than or equal to | ||
| | |||
{| class="wikitable" | {| class="wikitable" | ||
{{ | |{{xpd0|#expr:3<{{=}}2|gives={{!}}{{!}}}} | ||
{{ | |||
{{ | |||
{{ | |||
|- | |- | ||
| | |{{xpd0|#expr:3<{{=}}3|gives={{!}}{{!}}}} | ||
| | |||
{{ | |||
{{ | |||
|- | |- | ||
| | |{{xpd0|#expr:3<{{=}}4|gives={{!}}{{!}}}} | ||
{| | |||
{{ | |||
{{ | |||
|} | |} | ||
|- | |- | ||
! >= | |||
| | | Greater than or equal to | ||
| | | | ||
{| class="wikitable" | {| class="wikitable" | ||
| {{ | |{{xpd0|#expr:3>{{=}}2|gives={{!}}{{!}}}} | ||
|- | |- | ||
| {{ | |{{xpd0|#expr:3>{{=}}3|gives={{!}}{{!}}}} | ||
|- | |||
|{{xpd0|#expr:3>{{=}}4|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
! and | |||
| | | Logical AND | ||
| | | | ||
{| class="wikitable" | {| class="wikitable" | ||
| {{ | |{{xpd0|#expr:3 and 4|gives={{!}}{{!}}}} | ||
|- | |||
|{{xpd0|#expr:0 and 3|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:-3 and 0|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:0 and 0|gives={{!}}{{!}}}} | |||
|} | |} | ||
|- | |- | ||
! or | |||
| | | Logical OR | ||
| | | | ||
{| class="wikitable" | {| class="wikitable" | ||
| {{ | |{{xpd0|#expr:3 or 4|gives={{!}}{{!}}}} | ||
|- | |||
|{{xpd0|#expr:0 or 3|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:-3 or 0|gives={{!}}{{!}}}} | |||
|- | |||
|{{xpd0|#expr:0 or 0|gives={{!}}{{!}}}} | |||
|} | |} | ||
|} | |} | ||
The boolean operators consider 0 to be false and any other number to be true. An intermediate or final result "true" is identified with 1. Thus {{xpd0|#expr: (2 < 3) + 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 <nowiki>{{ #expr: {{#if:{{{a}}}|1|0}} or {{#if:{{{b}}}|1|0}} }} we can also use {{#if:{{{a}}}{{{b}}}|1|0}}}}</nowiki>. For negation, simply subtract from 1 or interchange then- and else-part. | |||
Precedence | Precedence: | ||
* | *{{xpd0|#expr: 2 - 3 + 4 / 5 * 6}} | ||
(+ and - have equal precedence, * and / also, both higher than the former two). | |||
* | |||
*{{xpd0|1=#expr: 2 = 5 < 3 + 4}} | |||
(first +, then =, then <). | |||
*{{xpd0 | *{{xpd0|#expr:1.234 + 1.234 round 1 + 1 }} | ||
(first additions, then round) | |||
*{{xpd0|#expr:3 * 4 mod 10 * 10 }} | |||
*{{ | |||
* | |||
* | |||
(mod and multiplication have equal precedence, evaluation from left to right) | |||
Parentheses can force a different precedence: {{xpd0|#expr: (2 + 3) * 4}} | |||
* | |||
Blank spaces are good for readability but not needed for working properly, except between not and an adjacent and/div/mod/not/or/round operator, and within numbers not allowed: | |||
*{{xpd0|#expr:7mod3}} | |||
*{{xpd0|#expr:7.5round0}} | |||
*{{xpd0|#expr:0and1}} | |||
*{{xpd0|#expr:0or not0}} | |||
*{{xpd0|#expr:0ornot0}} | |||
*{{xpd0|#expr:123 456}} | |||
*{{xpd0|#expr:not not3}} | |||
*{{xpd0|#expr:notnot3}} | |||
*{{xpd0|#expr:---2}} | |||
*{{xpd0|#expr:-+-2}} | |||
*{{xpd0|#expr:2*-3}} | |||
*{{ | *{{xpd0|#expr:-not-not-not0}} | ||
*{{ | *{{xpd0|#expr:2*/3}} | ||
*{{ | *{{xpd0|#expr:sinln1.1}} | ||
*{{xpd0|#expr:sin ln1.1}} | |||
==Numbers as input== | ==Numbers as input== | ||
| Line 480: | Line 422: | ||
*{{xpd0|#expr: 12.}} | *{{xpd0|#expr: 12.}} | ||
These equivalences | These equivalences are also relevant for #ifeq and #switch, see below. | ||
In [http://svn.wikimedia.org/doc/Expr_8php-source.html] we have | |||
define( 'EXPR_NUMBER_CLASS', '0123456789.' ); | |||
... | |||
elseif ( false !== strpos( EXPR_NUMBER_CLASS, $char ) ) { | |||
// Number | |||
if ( $expecting != 'expression' ) {throw new ExprError('unexpected_number');} | |||
// Find the rest of it | |||
$length = strspn( $expr, EXPR_NUMBER_CLASS, $p ); | |||
// Convert it to float, silently removing double decimal points | |||
$operands[] = floatval( substr( $expr, $p, $length ) ); | |||
$p += $length;$expecting = 'operator';continue;} | |||
Thus a number | Thus the part of the expression representing a number is a sequence of digits and points; due to [http://www.php.net/manual/en/function.floatval.php 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: | ||
Thus a number can only consist of one or more digits, or zero or more digits, a point, and zero or more digits. (For the purpose of evaluating an expression a plus or minus sign is considered a unary operator instead of part of the number.) | |||
Canonical form: | |||
*{{xpd0|#expr: 123}} | |||
*{{xpd0|#expr: 123.456}} | |||
*{{xpd0|#expr: 0.456}} | |||
*{{xpd0|#expr: 0}} | |||
*{{xpd0|#expr: 2.0E-5}} | |||
Accepted, although in some cases more or less odd: | |||
*{{xpd0|#expr: .456}} | |||
*{{xpd0|#expr: 123.}} | *{{xpd0|#expr: 123.}} | ||
*{{xpd0|#expr:000123. | *{{xpd0|#expr: 000123}} | ||
*{{xpd0|#expr:.}} | *{{xpd0|#expr: 123.456.789}} | ||
*{{xpd0|#expr: .}} | |||
*{{xpd0|#expr: 2e-5}} | |||
*{{xpd0|#expr: | *{{xpd0|#expr: 2E-5}} | ||
*{{xpd0|#expr: E}} | |||
*{{xpd0|#expr: e}} | |||
*{{xpd0|#expr: E-5}} | |||
*{{xpd0|#expr: e-5}} | |||
*{{xpd0|#expr: 1e-5}} | |||
Wrong: | Wrong: | ||
*{{xpd0|#expr: 123,456}} | *{{xpd0|#expr: 123,456}} | ||
*{{xpd0|#expr: 123 456}} | *{{xpd0|#expr: 123 456}} | ||
Due to the specifier R ("raw"), {{xpdoc|NUMBEROFARTICLES:R}} etc., i.e. numbers without group separators, which can be used in computations. | |||
As opposed to ParserFunctions, "[[Help:Magic_words#Language-dependent_word_conversions|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: | |||
As opposed to ParserFunctions, " | |||
*{{xpd5op3p3p3c||||||plural:1.000||a|||b|||c}} | *{{xpd5op3p3p3c||||||plural:1.000||a|||b|||c}} | ||
*{{xpd5op3p3p3c||||||plural:1,000||a|||b|||c}} | *{{xpd5op3p3p3c||||||plural:1,000||a|||b|||c}} | ||
| Line 555: | Line 475: | ||
== Numbers as output == | == Numbers as output == | ||
A non-integer result has a decimal point in it. Scientific notation is produced for numbers with small absolute value ( less than 1E-4) and for numbers with large absolute value ( greater than or equal to 1E+12; however, even within MediaWiki there is no uniformity, larger numbers in non-scientific notation and smaller numbers in scientific notation have been observed as output; the format of the same number can vary from preview to view, and by refreshing the page!). Thus numbers produced include (depending on the operating system of the server): | |||
*{{xpdoc|#expr: .000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123456789012345}} | |||
*{{ | *{{xpdoc|#expr: .00000123456789012345}} | ||
*{{ | *{{xpdoc|#expr: .0000123456789012345}} | ||
*{{ | *{{xpdoc|#expr: .000123456789012345}} | ||
*{{ | *{{xpdoc|#expr: 123456789012.345}} | ||
*{{ | *{{xpdoc|#expr: 1234567890123.45}} | ||
*{{ | *{{xpdoc|#expr: 12345678901234.5}} | ||
*{{xpdoc|#expr: 123456789012345}} | |||
*{{xpdoc|#expr: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456}} | |||
*{{ | *{{xpdoc|#expr: 1.234e4}} | ||
*{{ | *{{xpdoc|#expr: 1.234e-4}} | ||
*{{ | |||
*{{ | |||
*{{ | |||
For | For negative numbers simply a minus sign is prefixed: | ||
*{{ | *{{xpdoc|#expr: -123456789012345}} | ||
;Long <tt>YYYYMMDDhhmmss</tt> timestamps can run into the same problem: | |||
:{{xpdoc|CURRENTTIMESTAMP}}, | |||
:{{xpdoocc|#expr:|CURRENTTIMESTAMP}}. | |||
;Timestamps without seconds are 12 digits, just short enough: | |||
:{{xpdoc|#expr:{{CURRENTTIMESTAMP}}/100}} | |||
To avoid these problems and also increase accuracy, unless the result is represented by #expr exactly and in non-scientific notation, such as a not too large integer, do not use #expr in an expression to be evaluated by #expr or #ifexpr. Typically the result of a computational template could be needed in a further computation, so at least one version of such a template needs to give the result in a form suitable for that, e.g. {{tim|roote}} and {{tim|rooteval}}; for convenience, for the final result another version can be made simply calling the other one and applying #expr to the result, e.g. {{tim|rootfineval}}. | |||
The | Two methods for representing intermediate results are: | ||
1. The expression resulting from processing the expressions themselves, using #expr for branching only. | |||
For example, {{tim|powe}} produces the power of a number in the form of an expression: | |||
*{{ | *{{xpd2|powe|31.18|12}} | ||
However, the expression can get quite long, for {{tim|roote}} see [[Help:Calculation/example 1]]. Although [[Template:Long expression demo|long expressions]] are allowed, they give rise to a large post-expand include size and template argument size, for which limits exist. | |||
Applying #expr directly on a linked expression gives {{#expr:{{roote|.0000000000001}}}}, but it can also be used in a further computation, unlike the value just mentioned. | |||
2. Writing numbers splitting off factors which are powers of 10 but written plainly. | |||
Example: | |||
*{{ | *{{xpd1|gives=giving|rooteval|.0000000000001}} | ||
Intermediate results are also in such a form, preventing the growth of the expression like above. Again, #expr can be applied directly, as done in {{tim|rootfineval}}, | |||
giving {{fineval|.0000000000001}}, but the result can also be used in a further computation. | |||
Compare: | |||
*{{ | *{{xpd0|#expr:(.0000000000001)^(1/2)}} | ||
This uses the same method, but with intermediate application of #expr, giving an error because of internediate results in scientific notation. | |||
If | If the result of rounding a negative number is zero, the result is "-0". To avoid that, an expression ''x'' can be replaced by 0 + ( ''x'' ): | ||
*{{ | *{{xpd0|#expr: ( -0.2 round 0 )}} | ||
*{{xpd0|#expr: 1*(-0.2 round 0)}} | |||
*{{xpd0|#expr: 0+(-0.2 round 0)}} | |||
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{{e|23}}. | |||
==Accuracy== | |||
:''The accuracy and format of numeric results varies with the operating system of the server.'' | |||
Accuracy of the result of #expr is less than internally used within the computation of an expression: | |||
*{{xpdoc|#expr:(2/3)}} | |||
*{{ | *{{xpdoc|#expr:(2/3)*1000000-666666}} | ||
*{{xpdoocc|#expr:|#expr:(2/3)| *1000000-666666}} | |||
*{{xpdoc|#expr:1234567890.1234567890-1234567890}} (conclusion: <font color="red">'''16'''</font> or 17 digits of 1234567890.1234567890 used) | |||
*{{xpdoc|#expr:1234567890.1234567890}} (result is rounded to a total of <font color="red">'''12'''</font> digits) | |||
*{{xpdoocc|#expr:(|#expr:1234567890.1234567890| -1234567890)}} | |||
The | ;The [[w:en:Machine epsilon|macheps]] or smallest '''x''' such that '''1+x != 1''' appears to be near <tt>0.5^53 + 0.5^106</tt> or 1.1102230246251566636831481088739149080825883E-<font color="red">'''16'''</font> (see above): | ||
;<small>{{xpdoc|1=#expr:1=1+0.00000000000000011102230246251566636831481088739149080826}}</small> | |||
;<small>{{xpdoc|1=#expr:1=1+0.00000000000000011102230246251566636831481088739149080825}}</small> | |||
;That's the normal behaviour for [http://www.math.byu.edu/~schow/work/IEEEFloatingPoint.htm 64=1+52+11] bits (52 mantissa, 11 exponent). As explained above it is unrelated to the smallest expression result greater than '''1''': | |||
;{{xpdoc|#expr:1+0.000000000004999889392}} | |||
;{{xpdoc|#expr:1+0.000000000004999889391}} below about 1 + 5E-<font color="red">'''12'''</font>. | |||
==Branching depending on an expression== | ==Branching depending on an expression== | ||
The function [[ | The function [[m:ParserFunctions#.23ifexpr:|#ifexpr]] produces one of two specified results, depending on the value of a boolean expression involving numbers and booleans (not strings). Examples: | ||
;<nowiki>{{#ifexpr: {{CURRENTDOW}} = 0 or {{CURRENTDOW}} = 6 | weekEND | weekDAY}}</nowiki> yields '''{{#ifexpr: {{CURRENTDOW}} = 0 or {{CURRENTDOW}} = 6|weekEND|weekDAY}}''' because today is {{CURRENTDAYNAME}} and so {{xpd0|CURRENTDOW|gives=is}}. | |||
{{xpd2|1=#ifexpr:2^10=1024|2=1|3=0}} | |||
Note that rounding errors can affect a result: | |||
*{{xpd0|#expr:sin pi}} | |||
*{{xpd2|1=#ifexpr:sin pi=0|2=1|3=0}} | |||
*{{xpd2|#ifexpr:abs sin pi<1e-15|1|0}} | |||
Similarly: | |||
*{{ | *{{xpd0|1=#expr:sin pi=0}} | ||
*{{ | *{{xpd0|#expr:abs sin pi<1e-15}} | ||
==Comparisons== | |||
#The function [[m:ParserFunctions#.23ifeq:|#ifeq:]] compares numbers and strings for equality (equal if both represent the same number or both are equal strings). | |||
#The function [[m:ParserFunctions#.23switch:|#switch:]] compares one string with multiple others, and correspondingly produces one of multiple specified results. | |||
*{{ | *{{xpdopepepec|#switch:FR|UK|London|FR|Paris|NL|Amsterdam}} | ||
<!-- | |||
*{{ | *{{xpd|#switch:UK|UK|3=GB=London|4=FR=Paris}} | ||
*{{ | *{{xpd|#switch:ZZ|2=UK=London|3=FR=Paris|4=no match}} | ||
--> | |||
*{{xpd3|#ifeq:3|3.0|1|0}} | |||
*{{xpd3|#ifeq:3|03|1|0}} | |||
*{{xpd3|#ifeq:0.00003456|3.456E-05|1|0}} | |||
:*Note that '''#ifeq:''' unlike '''#expr:''' accepts exponential notation on input. | |||
:::* <nowiki>{{#ifexpr:0.00003456 = 3.456E-05|1|0}}</nowiki> gives "{{#ifexpr:0.00003456 = 3.456E-05|1|0}}" | |||
*{{xpd3|#ifeq:1234567890123|1234567890120|1|0}} | |||
*{{xpd3|#ifeq:1234567890123|1.23456789012E+12|1|0}} | |||
*{{xpd3|#ifeq:1234567890120|1.23456789012E+12|1|0}} | |||
*{{xpd3|#ifeq:1.234567890120E12|1.23456789012E+12|1|0}} | |||
*:Numerical comparisons don't depend on the output format, compare: | |||
*{{xpd0|#expr:1234567890123}} | |||
*{{xpd0|#expr:1234567890120}} | |||
[[ParserFunctions#.23ifeq:|#ifeq:]] allows to compare strings containing equal signs: | |||
{| | |||
!#switch form | |||
!#ifeq form | |||
|- | |||
|{{xpd|#switch:-1.0|2=-1=okay|3=fail|s=</td><td>}} | |||
|{{xpd|#ifeq:-1.0|-1|okay|fail|s=</td><td>}} | |||
|- | |||
|<code>"<nowiki>{{#switch: {{#expr:-1.0}} |-1=okay|fail}}</nowiki>"</code> gives "{{#switch: {{#expr:-1.0}} |-1=okay|fail}}" | |||
|- | |||
|{{xpd|1=#switch:a=b|2=a=b=okay|3=fail|s=</td><td>}} | |||
|{{xpd|1=#ifeq:a=b|2=a=b|3=okay|4=fail|s=</td><td>}} | |||
|- | |||
|{{xpd|1=#switch:a=c|2=a=b=fail|3=okay|s=</td><td>}} | |||
|{{xpd|1=#ifeq:a=c|2=a=b|3=fail|4=okay|s=</td><td>}} | |||
|}{{-}} | |||
==Length of expressions== | ==Length of expressions== | ||
To find the absolute value of a numeric expression x without using a separate template at least doubles the length of the expression: | |||
*''x''<tt>*(1-2*(</tt>''x''<tt><0))</tt> | |||
*x*<nowiki>{{#ifexpr:x>0|1|-1}}</nowiki> | |||
(The first is not only shorter but has also the advantage that for substitution one less "subst:" or <nowiki>{{{subst|}}}</nowiki> is needed.) | |||
Do not use | |||
*<nowiki>{{#ifexpr:x>0|x|-x}}</nowiki> | |||
for long expressions as it triples the length. | |||
Similarly do not use mod to round or conversely, because it doubles the length of the expression. | |||
Also providing a leading zero for the result of an expression if it is less than 10 doubles its length: | |||
*<nowiki>{{#ifexpr:x<10|0}}x</nowiki> | |||
This "exponential" growth of expressions, with much repetition, is due to the lack of variables (in the computer programming sense); however, see also [[VariablesExtension]]. | |||
Templates (subroutines) provide some of the functionality that variables offer: a template name is comparable with a variable name, while its content is comparable with the value of the variable. Alternatively, a template parameter can be assigned a value which can be used for multiple occurrences of the same parameter in the template. Thus e.g. x*(1-2*(x<0)) with a long expression x can be evaluated avoiding duplication of that expression, in two ways: | |||
*put the expression x in a template (multiple calls of the same template) | |||
*put x*(1-2*(x<0)) in a template with parameter x (use of a template with multiple occurrences of the same parameter) | |||
For the [[Wikipedia:Template limits|pre-expand include size maximum]] the first method does not help, but the second does. | |||
but | |||
If the number of possible results of a long expression is small, a switch allows arbitrary conversion, including the absolute value and providing a leading zero, etc., without repeating the expression. | |||
==Error messages== | |||
Examples for all known [[m:ParserFunctions#.23expr:|#expr:]] and [[m:ParserFunctions#.23ifexpr:|#ifexpr:]] error messages. The error texts are within the tags <strong class="error">..</strong>. Note that with the old preprocessor the "=" in "class=error" disturbs the numbering of unnamed parameters, if one of them produces an error message: <nowiki>{{t1|{{#expr:1/0}}}}</nowiki> gives {{t1|{{#expr:1/0}}}}. | |||
{| cellspacing="0" cellpadding="0" | |||
|- | |||
||'''Expression''' | |||
||'''Error message''' | |||
|- | |||
||{{xpd1|#expr:1/0|s=</td><td>}} | |||
|- | |||
||{{xpd1|#expr:2*|s=</td><td>}} | |||
|- | |||
||{{xpd1|#expr:1 2|s=</td><td>}} | |||
|- | |||
||{{xpd1|#ifexpr:1*/2|s=</td><td>}} | |||
|- | |||
||{{xpd1|#expr: 1 (2)|s=</td><td>}} | |||
|- | |||
||{{xpd1|#expr: (1 |s=</td><td>}} | |||
|- | |||
||{{xpd1|#expr: 1) |s=</td><td>}} | |||
|- | |||
||{{xpd1|#expr:2*123,456|s=   </td><td>}} | |||
|- | |||
||{{xpd1|#expr:{{{a}}}|s=</td><td>}} | |||
|- | |||
||{{xpd1|#ifexpr:3%2|s=</td><td>}} | |||
|- | |||
||{{xpd1|#ifexpr:abc|s=</td><td>}} | |||
|- | |||
||{{xpd1|#expr:abc.def|s=</td><td>}} | |||
|- | |||
|colspan="2"|{{<small> </small><tt>#expr:</tt>{{<small> </small><tt>x|102|1000*</tt>}}<tt><small> </small>18</tt><small> </small>}} gives {{#ifeq:{{ns:4}}|Meta|{{#expr:{{x|102|1000*}}18}}|{{#expr:1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*18}}}} | |||
|- | |||
|colspan="2"|{{<small> </small><tt>#expr:</tt>{{<small> </small><tt>x|102|1000*</tt>}}<tt><small> </small>179</tt><small> </small>}} gives {{#ifeq:{{ns:4}}|Meta|{{#expr:{{x|102|1000*}}179}}|{{#expr:1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*179}}}} | |||
|- | |||
|colspan="2"|{{<small> </small><tt>#expr:</tt>{{<small> </small><tt>x|102|1000*</tt>}}<tt><small> </small>180</tt><small> </small>}} gives {{#ifeq:{{ns:4}}|Meta|{{#expr:{{x|102|1000*}}180}}|{{#expr:1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*1000*180}}}} ( "INF", but depending on the operating system of the server it may also be e.g. "1.#INF") | |||
|- | |||
|colspan="2"|{{<small> </small><tt>#expr:</tt>{{<small> </small><tt>x|33|(1+(</tt>}}<small> </small><tt>1</tt><small> </small>{{<small> </small><tt>x|33|))</tt>}} }} gives {{#ifeq:{{ns:4}}|Meta|{{#expr:{{x|33|(1+(}}1{{x|33|))}}}}|{{#expr:(1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+(1)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))}}}} | |||
|- | |||
|colspan="2"|{{<small> </small><tt>#expr:</tt>{{<small> </small><tt>x|34|(1+(</tt>}}<small> </small><tt>1</tt><small> </small>{{<small> </small><tt>x|34|))</tt>}} }} gives {{#ifeq:{{ns:4}}|Meta|{{#expr:{{x|34|(1+(}}1{{x|34|))}}}}|{{#expr:(1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+((1+(1))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))}}}} | |||
|- | |||
|colspan="2"|{{xpd0|#expr:3.4.5.6}}   <small>(no feature, only an oddity)</small> | |||
|} | |||
Note: {{links-small|template|x}} copies a given string, here parts of an expression, for the specified times (max. 120). | Note: {{links-small|template|x}} copies a given string, here parts of an expression, for the specified times (max. 120), this help page shown on other projects actually evaluate its substituted output like 102 factors "1000" times "180" to get '''INF''' (infinity). | ||
Wikitext without error message from the parser functions, but typically | Wikitext without error message from the parser functions, but typically an error while using or attempting to use them: | ||
{| cellspacing="0" cellpadding="0" | {| cellspacing="0" cellpadding="0" | ||
| Line 743: | Line 697: | ||
|- | |- | ||
|valign="top"|<nowiki>{{#expr:2*3}</nowiki> | |valign="top"|<nowiki>{{#expr:2*3}</nowiki> | ||
|valign="top"| | |valign="top"| {{#expr:2*3} | ||
|(too few braces, the whole is interpreted as plain text) | |(too few braces, the whole is interpreted as plain text) | ||
|} | |} | ||
;A crude but informative "unrecognised word" error message can be generated intentionally. Only the first identified error is shown: | |||
:{{<tt> #expr: 2*</tt>{{<tt> #ifexpr: 3*4>10|toolarge|3*4 </tt>}} }} gives | |||
::{{#expr:2*{{#ifexpr:3*4>10|toolarge|3*4}}}}, | |||
:{{<tt> #expr: 2*</tt>{{<tt> #ifexpr: 3*4>10|too large|3*4 </tt>}} }} gives | |||
*< | ::{{#expr:2*{{#ifexpr:3*4>10|too large|3*4}}}}. | ||
See also [[Help:ParserFunctions#.23iferror:|#iferror]]. | |||
==Minus sign== | ==Minus sign== | ||
Only the | Only the ASCII [[hyphen]] ([[hyphen-minus]]) and [[minus sign]]s work as minus signs; dashes are not permitted. The output, however, will always be in the form of a hyphen-minus: | ||
{| class="wikitable" | |||
|hyphen-minus||{{xpd0|#expr:-12|gives={{!}}{{!}}}} | |||
{|class="wikitable" | |||
| {{xpd0|#expr:-12|gives={{! | |||
|- | |- | ||
| | |Unicode hyphen (U+2010, ‐) || <code>"{{#expr:‐12}}"</code> || "{{#expr:‐12}}" | ||
| <code>"&# | |||
| "{{#expr: | |||
|- | |- | ||
| minus sign | |[[Minus_sign#Character_codes|minus sign]] produced by &minus;||<code>"{{#expr:−12}}"</code> || "{{#expr:−12}}" | ||
| <code>"&# | |||
| "{{#expr: | |||
|- | |- | ||
| | |&minus;||<code>"{{<nowiki/>#expr:&minus;12}}"</code> || "{{#expr:−12}}" | ||
| { | |||
|- | |- | ||
| | |[[Dash#Em_dash|em dash]] produced by &mdash;||<code>"{{<nowiki/>#expr:—12}}"</code> || "{{#expr:—12}}" | ||
| <code>"&# | |||
| "{{#expr: | |||
|- | |- | ||
| | |&mdash;||<code>"{{<nowiki/>#expr:&mdash;12}}"</code> || "{{#expr:—12}}" | ||
| <code>"&# | |||
| "{{#expr:& | |||
|- | |- | ||
| | |[[Dash#En_dash|en dash]] produced by &ndash;||<code>"{{#expr:–12}}"</code> || "{{#expr:–12}}" | ||
| { | |||
|- | |- | ||
| | |&ndash;||<code>"{{<nowiki/>#expr:&ndash;12}}"</code> || "{{#expr:–12}}" | ||
| <code>" | |||
| "{{#expr:–12}}" | |||
|} | |} | ||
| Line 841: | Line 732: | ||
==Displaying numbers and numeric expressions== | ==Displaying numbers and numeric expressions== | ||
Guidelines such as | Guidelines such as [[WP:Manual of Style (dates and numbers)#Numbers]] focus on number display as end product. However, 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 | *use digits, not words | ||
*as mentioned above, use the hyphen as minus sign | *as mentioned above, use the hyphen as minus sign | ||
| Line 863: | Line 754: | ||
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 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. | ||
==Tactics for handling extreme numbers== | |||
<code>< | In the digital storage of numbers, the effects of [[truncation error]] on numeric precision might cause some extreme decimal numbers (above 1E13 or below 1E-12), or other E-notation numbers, to mismatch during comparisons. There are some tactics which can help, such as comparing results with "<code>#ifeq</code>" rather than "<code>#ifexpr</code>". | ||
; Comparing large numbers | |||
The floor function might mismatch the original value of a large number, by a tiny amount, and so comparisons can be made with <code>#ifeq</code> between separate expressions. For example: | |||
== | ::* <code><nowiki>{{#ifexpr: floor( 1.36E4 ) = 1.36E4|Equal|Differ}}</nowiki></code> gives "{{#ifexpr: floor( 1.36E4 ) = 1.36E4|Equal|Differ}}" | ||
* | ::* <code><nowiki>{{#ifexpr: floor( 1.33E4 ) = 1.33E4|Equal|Differ}}</nowiki></code> gives "{{#ifexpr: floor( 1.33E4 ) = 1.33E4|Equal|Differ}}" | ||
* | ::* <code><nowiki>{{#ifexpr: floor( 1.52E4 ) = 1.52E4|Equal|Differ}}</nowiki></code> gives "{{#ifexpr: floor( 1.52E4 ) = 1.52E4|Equal|Differ}}" | ||
::* <code><nowiki>{{#ifexpr: floor( 1.36E13 ) = 1.36E13|Equal|Differ}}</nowiki></code> gives "{{#ifexpr: floor( 1.36E13 ) = 1.36E13|Equal|Differ}}" | |||
::* <code><nowiki>{{#ifexpr: trunc( 1.36E13 ) = 1.36E13|Equal|Differ}}</nowiki></code> gives "{{#ifexpr: trunc( 1.36E13 ) = 1.36E13|Equal|Differ}}" | |||
* | |||
* | |||
{{ | However, using <code>#ifeq</code> to compare the results of 2 expressions can work: | ||
::* <code><nowiki>{{#ifeq: {{#expr:floor(1.33E4) }} | {{#expr:1.33E4}}|Equal|Differ}}</nowiki></code> gives "{{#ifeq: {{#expr:floor(1.33E4) }} | {{#expr:1.33E4}}|Equal|Differ}}" | |||
::* <code><nowiki>{{#ifeq: {{#expr:floor(1.36E13) }} | {{#expr:1.36E13}}|Equal|Differ}}</nowiki></code> gives "{{#ifeq: {{#expr:floor(1.36E13) }} | {{#expr:1.36E13}}|Equal|Differ}}" | |||
::* <code><nowiki>{{#ifeq: {{#expr:trunc(1.36E13) }} | {{#expr:1.36E13}}|Equal|Differ}}</nowiki></code> gives "{{#ifeq: {{#expr:trunc(1.36E13) }} | {{#expr:1.36E13}}|Equal|Differ}}" | |||
The truncation-error amount can usually be displayed by subtraction: | |||
::* <code><nowiki>{{#expr: floor(1.36E4) - 1.36E4 }}</nowiki></code> gives "{{#expr: floor(1.36E4) - 1.36E4 }}" | |||
::* <code><nowiki>{{#expr: floor(13600) - 13600 }}</nowiki></code> gives "{{#expr: floor(13600) - 13600 }}" | |||
::* <code><nowiki>{{#expr: floor(1.36E13) - 1.36E13 }}</nowiki></code> gives "{{#expr: floor(1.36E13) - 1.36E13 }}" | |||
::* <code><nowiki>{{#expr: trunc(1.36E13) - 1.36E13 }}</nowiki></code> gives "{{#expr: trunc(1.36E13) - 1.36E13 }}" | |||
There are similar workarounds to bypass other limitations due to [[truncation error]] in the handling of extreme numbers. | |||
[[Category: | ==See also== | ||
*[[mw:Help:Extension:ParserFunctions]] | |||
**[http://bugzilla.wikimedia.org/attachment.cgi?id=2751 ParserFunctions patch] ([[bugzilla:6068]]) | |||
*[[Help:Parser function]] (general considerations) | |||
*[[Help:Substitution]] | |||
*[[m:Category:Mathematical templates]] | |||
{{mediawiki}} | |||
{{Help navigation}} | |||
[[Category:Wikipedia text help]] | |||
[[Category:Wikipedia features]] | |||
Revision as of 11:35, 2 July 2013
- The accuracy and format of numeric results varies with the server; even on a single page, while for any rendering there is consistency within the page, there is no consistency among renderings.
The MediaWiki extension ParserFunctions enables users to perform calculations, for simple arithmetic or for functions as on a scientific calculator, with rounding, floor, logarithms (ln), sine, cosine, or modulo (etc.), plus boolean comparisons with "=" or "<" or ">=" etc.
The expr function evaluates numerical expressions, and also boolean expressions involving numbers and booleans (not strings). The syntax is
- {{ #expr: expression }} - Spaces are not required, but spaces/commas within numbers are not allowed.
The supported operators (roughly in order of precedence) are:
not, ^,
*, /, div, mod,
+, -,
round, trunc,
=, <>, !=, <=, >=,
and, and
or. Functions include: abs( ), ceil( ), floor( ), ln( ), sin( ), cos( ), tan( ), etc.
The precision supports 14-digit numbers (pi: 3.1415926535898, or longer on some servers) and E-notation ("1.54E17"), but truncation error can cause mismatches on comparisons of very large numbers or tiny decimals, so see below: "Tactics for handling extreme numbers".
Operators
| Operator | Operation | Examples | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| none | none |
Wrong:
| |||||||||||||||||||||||||||
| exp | e to the specified power |
Compare:
| |||||||||||||||||||||||||||
| ln | Natural logarithm |
Hence, the base ten logarithm of e.g. 2:
| |||||||||||||||||||||||||||
| abs |
| ||||||||||||||||||||||||||||
| trunc |
| ||||||||||||||||||||||||||||
| floor |
| ||||||||||||||||||||||||||||
| ceil |
| ||||||||||||||||||||||||||||
| sin |
With an angle in degrees, e.g. 30°:
| ||||||||||||||||||||||||||||
| cos |
| ||||||||||||||||||||||||||||
| tan |
| ||||||||||||||||||||||||||||
| asin |
| ||||||||||||||||||||||||||||
| acos |
| ||||||||||||||||||||||||||||
| atan |
| ||||||||||||||||||||||||||||
| + | Unary + sign |
| |||||||||||||||||||||||||||
| - | Unary - sign (negation) |
| |||||||||||||||||||||||||||
| not | Unary NOT, logical NOT |
| |||||||||||||||||||||||||||
| ^ | Power |
| |||||||||||||||||||||||||||
| * | Multiplication |
| |||||||||||||||||||||||||||
| / | Division, same as div |
| |||||||||||||||||||||||||||
| div | Division, same as /, not integer division |
| |||||||||||||||||||||||||||
| mod | "Modulo", remainder of division after truncating both operands to an integer (PHP operator %). Caveat, div and mod are different from all programming languages. This has been fixed (but needs to be committed), see bugzilla:6068. |
| |||||||||||||||||||||||||||
| + | Addition |
| |||||||||||||||||||||||||||
| - | Subtraction |
| |||||||||||||||||||||||||||
| round | Rounds off the number on the left to the power of 1/10 given on the right (PHP function round) |
| |||||||||||||||||||||||||||
| = | Equality (numerical incl. logical) |
| |||||||||||||||||||||||||||
| <> | Inequality, same as != |
| |||||||||||||||||||||||||||
| != | Inequality, same as <>, logical xor |
| |||||||||||||||||||||||||||
| < | Less than |
| |||||||||||||||||||||||||||
| > | Greater than |
| |||||||||||||||||||||||||||
| <= | Less than or equal to |
| |||||||||||||||||||||||||||
| >= | Greater than or equal to |
| |||||||||||||||||||||||||||
| and | Logical AND |
| |||||||||||||||||||||||||||
| or | Logical OR |
|
The boolean operators consider 0 to be false and any other number to be true. An intermediate or final result "true" is identified with 1. Thus "{{#expr: (2 < 3) + 1}}" gives "2" [90]. 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:
"{{#expr: 2 - 3 + 4 / 5 * 6}}"gives "3.8" [91]
(+ and - have equal precedence, * and / also, both higher than the former two).
"{{#expr: 2 = 5 < 3 + 4}}"gives "1" [92]
(first +, then =, then <).
"{{#expr:1.234 + 1.234 round 1 + 1}}"gives "2.47" [93]
(first additions, then round)
"{{#expr:3 * 4 mod 10 * 10}}"gives "20" [94]
(mod and multiplication have equal precedence, evaluation from left to right)
Parentheses can force a different precedence: "{{#expr: (2 + 3) * 4}}" gives "20" [95]
Blank spaces are good for readability but not needed for working properly, except between not and an adjacent and/div/mod/not/or/round operator, and within numbers not allowed:
"{{#expr:7mod3}}"gives "1" [96]"{{#expr:7.5round0}}"gives "8" [97]"{{#expr:0and1}}"gives "0" [98]"{{#expr:0or not0}}"gives "1" [99]"{{#expr:0ornot0}}"gives "Expression error: Unrecognized word "ornot"." [100]"{{#expr:123 456}}"gives "Expression error: Unexpected number." [101]"{{#expr:not not3}}"gives "1" [102]"{{#expr:notnot3}}"gives "Expression error: Unrecognized word "notnot"." [103]
"{{#expr:---2}}"gives "-2" [104]"{{#expr:-+-2}}"gives "2" [105]"{{#expr:2*-3}}"gives "-6" [106]"{{#expr:-not-not-not0}}"gives "-1" [107]"{{#expr:2*/3}}"gives "Expression error: Unexpected / operator." [108]"{{#expr:sinln1.1}}"gives "Expression error: Unrecognized word "sinln"." [109]"{{#expr:sin ln1.1}}"gives "0.095165945236752" [110]
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.
These equivalences are also relevant for #ifeq and #switch, see below.
In [113] we have
define( 'EXPR_NUMBER_CLASS', '0123456789.' );
...
elseif ( false !== strpos( EXPR_NUMBER_CLASS, $char ) ) {
// Number
if ( $expecting != 'expression' ) {throw new ExprError('unexpected_number');}
// Find the rest of it
$length = strspn( $expr, EXPR_NUMBER_CLASS, $p );
// Convert it to float, silently removing double decimal points
$operands[] = floatval( substr( $expr, $p, $length ) );
$p += $length;$expecting = 'operator';continue;}
Thus 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:
Thus a number can only consist of one or more digits, or zero or more digits, a point, and zero or more digits. (For the purpose of evaluating an expression a plus or minus sign is considered a unary operator instead of part of the number.)
Canonical form:
"{{#expr: 123}}"gives "123" [114]"{{#expr: 123.456}}"gives "123.456" [115]"{{#expr: 0.456}}"gives "0.456" [116]"{{#expr: 0}}"gives "0" [117]"{{#expr: 2.0E-5}}"gives "2.0E-5" [118]
Accepted, although in some cases more or less odd:
"{{#expr: .456}}"gives "0.456" [119]"{{#expr: 123.}}"gives "123" [120]"{{#expr: 000123}}"gives "123" [121]"{{#expr: 123.456.789}}"gives "123.456" [122]"{{#expr: .}}"gives "0" [123]"{{#expr: 2e-5}}"gives "2.0E-5" [124]"{{#expr: 2E-5}}"gives "2.0E-5" [125]"{{#expr: E}}"gives "2.718281828459" [126]"{{#expr: e}}"gives "2.718281828459" [127]"{{#expr: E-5}}"gives "-2.281718171541" [128]"{{#expr: e-5}}"gives "-2.281718171541" [129]"{{#expr: 1e-5}}"gives "1.0E-5" [130]
Wrong:
"{{#expr: 123,456}}"gives "Expression error: Unrecognized punctuation character ","." [131]"{{#expr: 123 456}}"gives "Expression error: Unexpected number." [132]
Due to the specifier R ("raw"), Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w → "1626" [133] etc., i.e. numbers without group separators, which can be used in computations.
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.
Numbers as output
A non-integer result has a decimal point in it. Scientific notation is produced for numbers with small absolute value ( less than 1E-4) and for numbers with large absolute value ( greater than or equal to 1E+12; however, even within MediaWiki there is no uniformity, larger numbers in non-scientific notation and smaller numbers in scientific notation have been observed as output; the format of the same number can vary from preview to view, and by refreshing the page!). Thus numbers produced include (depending on the operating system of the server):
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1.2345678901234E-106" [134]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1.2345678901234E-6" [135]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1.2345678901235E-5" [136]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "0.00012345678901234" [137]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "123456789012.35" [138]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1234567890123.4" [139]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "12345678901234" [140]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1.2345678901234E+14" [141]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1.2345678901235E+105" [142]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "12340" [143]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "0.0001234" [144]
For negative numbers simply a minus sign is prefixed:
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "-1.2345678901234E+14" [145]
- Long YYYYMMDDhhmmss timestamps can run into the same problem
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "20261105065034" [146],- Template:Xpdoocc.
- Timestamps without seconds are 12 digits, just short enough
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "202611050650.34" [147]
To avoid these problems and also increase accuracy, unless the result is represented by #expr exactly and in non-scientific notation, such as a not too large integer, do not use #expr in an expression to be evaluated by #expr or #ifexpr. Typically the result of a computational template could be needed in a further computation, so at least one version of such a template needs to give the result in a form suitable for that, e.g. Template:roote and Template:rooteval; for convenience, for the final result another version can be made simply calling the other one and applying #expr to the result, e.g. Template:rootfineval.
Two methods for representing intermediate results are:
1. The expression resulting from processing the expressions themselves, using #expr for branching only.
For example, Template:powe produces the power of a number in the form of an expression:
However, the expression can get quite long, for Template:roote see Help:Calculation/example 1. Although long expressions are allowed, they give rise to a large post-expand include size and template argument size, for which limits exist.
Applying #expr directly on a linked expression gives Expression error: Unrecognized punctuation character "["., but it can also be used in a further computation, unlike the value just mentioned.
2. Writing numbers splitting off factors which are powers of 10 but written plainly.
Example:
Intermediate results are also in such a form, preventing the growth of the expression like above. Again, #expr can be applied directly, as done in Template:rootfineval, giving Template:Fineval, but the result can also be used in a further computation.
Compare:
"{{#expr:(.0000000000001)^(1/2)}}"gives "3.1622776601684E-7" [148]
This uses the same method, but with intermediate application of #expr, giving an error because of internediate results in scientific notation.
If the result of rounding a negative number is zero, the result is "-0". To avoid that, an expression x can be replaced by 0 + ( x ):
"{{#expr: ( -0.2 round 0 )}}"gives "-0" [149]"{{#expr: 1*(-0.2 round 0)}}"gives "-0" [150]"{{#expr: 0+(-0.2 round 0)}}"gives "0" [151]
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.
Accuracy
- The accuracy and format of numeric results varies with the operating system of the server.
Accuracy of the result of #expr is less than internally used within the computation of an expression:
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "0.66666666666667" [152]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "0.66666666662786" [153]- Template:Xpdoocc
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "0.12345671653748" [154] (conclusion: 16 or 17 digits of 1234567890.1234567890 used)Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1234567890.1235" [155] (result is rounded to a total of 12 digits)- Template:Xpdoocc
- The macheps or smallest x such that 1+x != 1 appears to be near 0.5^53 + 0.5^106 or 1.1102230246251566636831481088739149080825883E-16 (see above)
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "0" [156]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1" [157]
- That's the normal behaviour for 64=1+52+11 bits (52 mantissa, 11 exponent). As explained above it is unrelated to the smallest expression result greater than 1
Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1.000000000005" [158]Template:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/wTemplate:Xpd/w→ "1.000000000005" [159] below about 1 + 5E-12.
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 Thursday and so
"{{CURRENTDOW}}"is "4" [160].
Note that rounding errors can affect a result:
"{{#expr:sin pi}}"gives "1.2246467991474E-16" [161]- Template:Xpd2
- Template:Xpd2
Similarly:
Comparisons
- The function #ifeq: compares numbers and strings for equality (equal if both represent the same number or both are equal strings).
- The function #switch: compares one string with multiple others, and correspondingly produces one of multiple specified results.
- Note that #ifeq: unlike #expr: accepts exponential notation on input.
- {{#ifexpr:0.00003456 = 3.456E-05|1|0}} gives "1"
- Template:Xpd3
- Template:Xpd3
- Template:Xpd3
- Template:Xpd3
- Numerical comparisons don't depend on the output format, compare:
"{{#expr:1234567890123}}"gives "1234567890123" [164]"{{#expr:1234567890120}}"gives "1234567890120" [165]
#ifeq: allows to compare strings containing equal signs:
| #switch form | #ifeq form | ||
|---|---|---|---|
{{#switch:-1.0|-1=okay|fail}} | fail | {{#ifeq:-1.0|-1|okay|fail}} | okay |
"{{#switch: {{#expr:-1.0}} |-1=okay|fail}}" gives "okay"
| |||
{{#switch:a=b|a=b=okay|fail}} | fail | {{#ifeq:a=b|a=b|okay|fail}} | okay |
{{#switch:a=c|a=b=fail|okay}} | okay | {{#ifeq:a=c|a=b|fail|okay}} | okay |
Length of expressions
To find the absolute value of a numeric expression x without using a separate template at least doubles the length of the expression:
- x*(1-2*(x<0))
- x*{{#ifexpr:x>0|1|-1}}
(The first is not only shorter but has also the advantage that for substitution one less "subst:" or {{{subst|}}} is needed.)
Do not use
- {{#ifexpr:x>0|x|-x}}
for long expressions as it triples the length.
Similarly do not use mod to round or conversely, because it doubles the length of the expression.
Also providing a leading zero for the result of an expression if it is less than 10 doubles its length:
- {{#ifexpr:x<10|0}}x
This "exponential" growth of expressions, with much repetition, is due to the lack of variables (in the computer programming sense); however, see also VariablesExtension.
Templates (subroutines) provide some of the functionality that variables offer: a template name is comparable with a variable name, while its content is comparable with the value of the variable. Alternatively, a template parameter can be assigned a value which can be used for multiple occurrences of the same parameter in the template. Thus e.g. x*(1-2*(x<0)) with a long expression x can be evaluated avoiding duplication of that expression, in two ways:
- put the expression x in a template (multiple calls of the same template)
- put x*(1-2*(x<0)) in a template with parameter x (use of a template with multiple occurrences of the same parameter)
For the pre-expand include size maximum the first method does not help, but the second does.
If the number of possible results of a long expression is small, a switch allows arbitrary conversion, including the absolute value and providing a leading zero, etc., without repeating the expression.
Error messages
Examples for all known #expr: and #ifexpr: error messages. The error texts are within the tags <strong class="error">..</strong>. Note that with the old preprocessor the "=" in "class=error" disturbs the numbering of unnamed parameters, if one of them produces an error message: {{t1|{{#expr:1/0}}}} gives Template:T1.
| Expression | Error message |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| Template:Xpd1 | |
| {{ #expr:{{ x|102|1000*}} 18 }} gives 1.8E+307 | |
| {{ #expr:{{ x|102|1000*}} 179 }} gives 1.79E+308 | |
| {{ #expr:{{ x|102|1000*}} 180 }} gives INF ( "INF", but depending on the operating system of the server it may also be e.g. "1.#INF") | |
| {{ #expr:{{ x|33|(1+(}} 1 {{ x|33|))}} }} gives Expression error: Unclosed bracket. | |
| {{ #expr:{{ x|34|(1+(}} 1 {{ x|34|))}} }} gives Expression error: Stack exhausted. | |
"{{#expr:3.4.5.6}}" gives "3.4" [166] (no feature, only an oddity)
| |
Note: Template:Links-small copies a given string, here parts of an expression, for the specified times (max. 120), this help page shown on other projects actually evaluate its substituted output like 102 factors "1000" times "180" to get INF (infinity).
Wikitext without error message from the parser functions, but typically an error while using or attempting to use them:
| {{{#expr:2*3}}} | {{{#expr:2*3}}} | (triple braces, the whole is interpreted as parameter tag with parameter name "#expr:2*3") |
| {{#expr:2*3}}} | 6} | (one closing brace too many; the last of the three is interpreted as plain text, so that the rest works fine) |
| {{{#expr:2*3}} | {6 | (one opening brace too many; the first of the three is interpreted as plain text, so that the rest works fine) |
| {{#expr:2*3} | {{#expr:2*3} | (too few braces, the whole is interpreted as plain text) |
- A crude but informative "unrecognised word" error message can be generated intentionally. Only the first identified error is shown
- {{ #expr: 2*{{ #ifexpr: 3*4>10|toolarge|3*4 }} }} gives
- Expression error: Unrecognized word "toolarge".,
- {{ #expr: 2*{{ #ifexpr: 3*4>10|too large|3*4 }} }} gives
- Expression error: Unrecognized word "too"..
See also #iferror.
Minus sign
Only the ASCII hyphen (hyphen-minus) and minus signs work as minus signs; dashes are not permitted. The output, however, will always be in the form of a hyphen-minus:
| hyphen-minus | "{{#expr:-12}}" |
"-12" | [167] |
| Unicode hyphen (U+2010, ‐) | "{{#expr:‐12}}" |
"Expression error: Unrecognized punctuation character "‐"." | |
| minus sign produced by − | "{{#expr:−12}}" |
"-12" | |
| − | "{{#expr:−12}}" |
"-12" | |
| em dash produced by — | "{{#expr:—12}}" |
"Expression error: Unrecognized punctuation character "—"." | |
| — | "{{#expr:—12}}" |
"Expression error: Unrecognized punctuation character "&"." | |
| en dash produced by – | "{{#expr:–12}}" |
"Expression error: Unrecognized punctuation character "–"." | |
| – | "{{#expr:–12}}" |
"Expression error: Unrecognized punctuation character "&"." |
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
Guidelines such as WP:Manual of Style (dates and numbers)#Numbers focus on number display as end product. However, 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×1023
Examples:
"{{#expr:three}}"gives "Expression error: Unrecognized word "three"." [168]"{{#expr:2<3}}"gives "1" [169]"{{#expr:2≤3}}"gives "Expression error: Unrecognized punctuation character "≤"." [170]"{{#expr:2<=3}}"gives "1" [171]"{{#expr:2>3}}"gives "0" [172]"{{#expr:2≥3}}"gives "Expression error: Unrecognized punctuation character "≥"." [173]"{{#expr:2>=3}}"gives "0" [174]"{{#expr:2*3}}"gives "6" [175]"{{#expr:2×3}}"gives "Expression error: Unrecognized punctuation character "×"." [176]"{{#expr:2,300}}"gives "Expression error: Unrecognized punctuation character ","." [177]"{{#expr:6E23}}"gives "6.0E+23" [178]
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.
Tactics for handling extreme numbers
In the digital storage of numbers, the effects of truncation error on numeric precision might cause some extreme decimal numbers (above 1E13 or below 1E-12), or other E-notation numbers, to mismatch during comparisons. There are some tactics which can help, such as comparing results with "#ifeq" rather than "#ifexpr".
- Comparing large numbers
The floor function might mismatch the original value of a large number, by a tiny amount, and so comparisons can be made with #ifeq between separate expressions. For example:
{{#ifexpr: floor( 1.36E4 ) = 1.36E4|Equal|Differ}}gives "Differ"{{#ifexpr: floor( 1.33E4 ) = 1.33E4|Equal|Differ}}gives "Equal"{{#ifexpr: floor( 1.52E4 ) = 1.52E4|Equal|Differ}}gives "Equal"{{#ifexpr: floor( 1.36E13 ) = 1.36E13|Equal|Differ}}gives "Differ"{{#ifexpr: trunc( 1.36E13 ) = 1.36E13|Equal|Differ}}gives "Differ"
However, using #ifeq to compare the results of 2 expressions can work:
{{#ifeq: {{#expr:floor(1.33E4) }} | {{#expr:1.33E4}}|Equal|Differ}}gives "Equal"{{#ifeq: {{#expr:floor(1.36E13) }} | {{#expr:1.36E13}}|Equal|Differ}}gives "Equal"{{#ifeq: {{#expr:trunc(1.36E13) }} | {{#expr:1.36E13}}|Equal|Differ}}gives "Equal"
The truncation-error amount can usually be displayed by subtraction:
{{#expr: floor(1.36E4) - 1.36E4 }}gives "-1.8189894035459E-12"{{#expr: floor(13600) - 13600 }}gives "0"{{#expr: floor(1.36E13) - 1.36E13 }}gives "-0.001953125"{{#expr: trunc(1.36E13) - 1.36E13 }}gives "-0.001953125"
There are similar workarounds to bypass other limitations due to truncation error in the handling of extreme numbers.
See also
- mw:Help:Extension:ParserFunctions
- Help:Parser function (general considerations)
- Help:Substitution
- m:Category:Mathematical templates