Page MenuHomePhabricator

Support decimal math (bc extension) in #expr ParserFunction to avoid floating-point surprises
Open, LowPublicFeature

Description

Recent threads on wikitech-l have pointed out that non-integer arithmetic done via the #expr parser function sometimes produces results unexpected by end users, due to the mismatch between the binary floating point used internally and the decimal input/output that the end-users work with.

While it's tempting to just tell people "that's how computers work, deal with it", that's a bit silly. :) PHP provides a standard module for arbitrary-precision decimal math ('bc').

Setting some decently large but not huge precision and using this for #expr math when the extension is available would probably provide more consistent results, and performance would not be significantly affected since this is a tiny portion of text processing time.

One thing to note however is that results would still be inconsistent between installs with BC available and those without, so third-party installs might not get the template results they want.

Some examples of "surprises" from the thread:

  • {{#expr:floor(0.00007*100000)}} = 6 (expect 7)
  • {{#expr:0.07*100 = 7}} is 0/False (expect 1/True)
  • {{#expr:5/6 = (1/6)*5}} is 0/False (expect 1/True... but this might still not work with fixed-precision math automatically; that needs a fuzzy delta in the comparison)

Version: unspecified
Severity: enhancement
URL: http://www.php.net/bc

Details

Reference
bz17468

Event Timeline

bzimport raised the priority of this task from to Low.Nov 21 2014, 10:27 PM
bzimport added a project: ParserFunctions.
bzimport set Reference to bz17468.
bzimport added a subscriber: Unknown Object (MLST).

Bug 6356 has a very old patch which implements this for the mod operator only.

Created attachment 5808
Handle BC math in Expr:

Pretty straightforward patch to conditionally handle some options (the $bc array in Expr) with BC. Also sets precision if the server admin defines one--defaults to php.ini, which is 0 by defaults, could use a sane setting.

Attached:

Implemented in r47200 and reverted.

Note the revert was due to getting results from some calculations with unexpectedly large numbers of decimal places, and possibly other problems.

We should ensure that there's a test suite covering these issues before recommitting.

audreyt wrote:

Hi Chad, thank you for the patch!

As you may already know, MediaWiki is currently revamping its PHP-based parser
into a "Parsoid" prototype component, to support the rich-text Visual Editor
project:

https://www.mediawiki.org/wiki/Parsoid
https://www.mediawiki.org/wiki/Visual_editor

Folks interested in enhancing the parser's capabilities are very much welcome
to join the Parsoid project, and contribute patches as Git branches:

https://www.mediawiki.org/wiki/Git/Tutorial#How_to_submit_a_patch

Compared to .diff attachments in Bugzilla tickets, Git branches are much easier
for us to review, refine and merge features together.

Each change set has a distinct URL generated by the "git review" tool, which
can be referenced in Bugzilla by pasting its gerrit.wikimedia.org URL as a
comment.

If you run into any issues with the patch process, please feel free to ask on
irc.freenode.net #wikimedia-dev and the wikitext-l mailing list. Thank you!

{{ #expr: (43.09 - 43) }} = 0.090000000000003
→ rounding needed for a simple difference.

Aklapper changed the subtype of this task from "Task" to "Feature Request".Feb 4 2022, 11:01 AM
Aklapper removed a subscriber: wikibugs-l-list.