After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 465747 - Wrong number comparison in XPath expression including sum()
Wrong number comparison in XPath expression including sum()
Status: RESOLVED NOTABUG
Product: libxslt
Classification: Platform
Component: general
1.1.21
Other Linux
: Normal critical
: ---
Assigned To: Daniel Veillard
libxml QA maintainers
Depends on:
Blocks:
 
 
Reported: 2007-08-11 18:29 UTC by robert.reitenbach
Modified: 2007-08-13 01:05 UTC
See Also:
GNOME target: ---
GNOME version: 2.19/2.20


Attachments
XML file allowing to show this bug (2.40 KB, application/xml)
2007-08-11 18:32 UTC, robert.reitenbach
Details

Description robert.reitenbach 2007-08-11 18:29:56 UTC
<?xml version="1.0" encoding="UTF-8"?>
<!--
	This file shows a bug in the xmlstarlet comand line utility, that
	itself uses libxml2 and libxslt.
	Used with libxslt v1.1.21 and libxml2 v2.6.29

	The expression '//T[V!=(AV+sum(As/A/M))]' will find select records for
	which the expression is not true!

	Here the used command line:
		xml sel -t -m '//T[V!=(AV+sum(As/A/M))]' -v V -o ' | ' -v AV -o ' | ' -v 'AV+sum(As/A/M)' -n bug.xml 

	It will select records that match the expression //T[V!=(AV+sum(As/A))]
	and then show the value of 'V' of 'AV' and of 'AV+sum(As/A/M)'
-->
<D>
	<!--
		Elements that are wrongly selected and demonstrate the issue.
	-->
	<!--
		Shows:
			268.09 | 266.99 | 268.09
		How comes that the record is matched if the calculation of 
		AV + sum(As/A/M) equals to V?
	-->
	<T>
		<V>268.09</V>
		<AV>266.99</AV>
		<As>
			<A>
				<M>1.1</M>
			</A>
		</As>
	</T>
	<!--
		Shows:
			21.12 | 16.63 | 21.12
		How comes that the record is matched if the calculation of 
		AV + sum(As/A/M) equals to V?
	-->
	<T>
		<V>21.12</V>
		<AV>16.63</AV>
		<As>
			<A>
				<M>4.49</M>
			</A>
		</As>
	</T>
	<!--
		Shows:
			81.88 | 71.76 | 81.88
		The calculation of AV + sum(As/A/M) equals to V therefore
		this record should not be selected
	-->
	<T>
		<V>81.88</V>
		<AV>71.76</AV>
		<As>
			<A>
				<M>10.12</M>
			</A>
		</As>
	</T>
	<!--
		Shows:
			7.95 | 6.05 | 7.949999999999999
		This record is apparenbtly matched because the calculation of
		AV + sum(As/A/M) equals to 7.949999999999999 instead to 7.95 
	-->
	<T>
		<V>7.95</V>
		<AV>6.05</AV>
		<As>
			<A>
				<M>1.9</M>
			</A>
		</As>
	</T>
	<!--
		This is a strange case, it shows correctly for the explained
		expression:
			10.36 | 8.96 | 10.36

		But for an expression that uses a substraction it will show:
			10.36 | 8.96 | 8.959999999999999

		Here the expression for the substraction:

		xml sel -t -m  '//T[AV!=(V - sum(As/A/M))]' -v V -o ' | ' -v AV -o ' | ' -v 'V - sum(As/A/M)' -n bug.xml
	-->
	<T>
		<V>10.36</V>
		<AV>8.96</AV>
		<As>
			<A>
				<M>1.4</M>
			</A>
		</As>
	</T>



	<!--
		Positive examples, i.e. they are detected correctly	
	-->
	<!--
		Shows:
			62.39 | 60.52 | 64.26
	-->
	<T>
		<V>62.39</V>
		<AV>60.52</AV>
		<As>
			<A>
				<M>1.87</M>
			</A>
			<A>
				<M>1.87</M>
			</A>
		</As>
	</T>
	<!--
		Shows:
			237.95 | 226.05 | 249.85
	-->
	<T>
		<V>237.95</V>
		<AV>226.05</AV>
		<As>
			<A>
				<M>11.9</M>
				<M>11.9</M>
			</A>
		</As>
	</T>
</D>
Comment 1 robert.reitenbach 2007-08-11 18:32:15 UTC
Created attachment 93503 [details]
XML file allowing to show this bug

The same file as in the bug text
Comment 2 robert.reitenbach 2007-08-11 18:35:28 UTC
I have tasted it also with different Linux and Windows versions of xmlstarlet that use an older version of libxslt, so it seems to be platform independent.
Comment 3 William M. Brack 2007-08-12 00:51:56 UTC
You have an incorrect expectation.  Whenever floating point arithmetic is performed in a program (and that includes the conversion from Ascii text into binary double within XPath), there is a high probability that "rounding errors" will occur.  Your "select" statement is testing for inequality, i.e. two floating point numbers are not *exactly* (bit-for-bit) equal, and this will usually be true even though the numbers being compared differ by only the rounding error.
Comment 4 robert.reitenbach 2007-08-12 10:13:34 UTC
Hello William,

it might be that it is a rounding error (at least the examples 4 and 5 show this clearly), nevertheless the same examples work correctly with another XML tool (Stylus Studio). I find the xmlstarlet utility very handy for scripted tests, but we stumbled about this. 

The strange thing is that the rounding error appears only in two examples (records 4 and 5) for all the others the cast back to a string has the same value.

In any case it is in the your hands to consider this as a bug or not. I'd appreciate if you could give a hint how to obtain correct results for the expected verification.

With best regards,

Robert
Comment 5 William M. Brack 2007-08-13 01:05:07 UTC
I cannot comment on the internals of Stylus Studio, but for libxml2 XPath works internally with "doubles", and that is what is behind the behaviour which you describe as a "bug".  There are many (good) reasons why libxml2 has chosen to implement it's XPath in this way, and it will not be changed.

If you have some doubt about whether "rounding error" explains your other test cases, try the following program:

#include <stdio.h>
#include <stdlib.h>
int main(int nargs, char **argv) {
char *cV = "268.09", *cAV = "266.99", *cM = "1.1";
double V, AV, M;
        AV = atof(cAV); V = atof(cV); M = atof(cM);
        if (V != (AV + M)) {
                printf("Differs: V = %f, AV = %f, M = %f\n" 
                        "Error is %e\n", V, AV, M, V - (AV + M));
        } else {
                printf("Values are equal\n");
        }
        return 0;
}

On my testing system (i686) this yields:
[bill@bbsuper bug465747]$ ./test
Differs: V = 268.090000, AV = 266.990000, M = 1.100000
Error is -3.419487e-14

As far as implementing your verification, from a general computational point of view you should check that the absolute difference between the value found and the value expected is less than some constant (e.g.
   abs(V - (AV+sum(As/A/M))) < .00000001
From an XPath perspective, however, this is not an easy thing to do.

In any event, this is not a bug.