MATLAB Answers

Identical math operations in C++ and matlab differ by ~1% (10^11 in this case!)

17 views (last 30 days)
M S
M S on 29 Oct 2011
Hello,
I have a single (VERY LONG) line of code written in both C++ and matlab that evaluates a mathematical expression. The expression is just under 31,000 characters long, so it's pretty darn complicated.
When I evaluate this expression in matlab vs. C++ I get very different numbers:
MATLAB: 31856235311612.7
C++: 31745938896594.422
However, as you'll probably notice, they're not different enough to think I made a mistake in the transfer. I basically just copied and pasted the expression from C++, so no issues there.
I have two similar expressions of lower order that I also ported; one on the order of 10^9 (differs by about 1%), and one of order 10^7 which does not suffer the same magnitude of error:
MATLAB=3087973.34551207
C++=3087973.3455120716
The question is, which is "correct", and from where are these differences arising? I'm happy to provide code, but the first entry code is a 31,000 character expression!
FYI, in C++ all variables are stored as doubles.

Accepted Answer

Jan
Jan on 29 Oct 2011
A much simpler example:
MATLAB uses FDLIBM for the calculation of ACOS. I've added this library to a C-mex file also and compared the results of:
a = [ 0.82924747834055368, ...
0.55849526207902467, ...
-0.020776474703722032];
b = [-0.82889260818746668, ...
-0.55895647212964961, ...
0.022465670623305872];
acos(dot(a, b))
I found differences between the values calculated by C and Matlab up to 32768 EPS, depending on the C-compiler and the input values.
Let's look on the sensitivities:
b_var = b + [0, eps, 0];
acos(dot(a, b)) - acos(dot(a, b_var))
>> 1.2434e-013
This means that tiny differences in the input are amplified by the factor 560. This seems to be small. But together with some cancellation effects, such differences can explode: [EDITED]
r = 1 / (3.13980602793225 - acos(dot(a, b)));
>> r = 2.2518e+014
r_var = 1 / (3.13980602793225 - acos(dot(a, b_var)));
>> r_var = 7.7648e+012
Now the analysis of the sensitivity would reveal, that the algorithm is such instable, that it cannot be used to determine a single siginificant digit.
Conclusion: Calculating values using a 31'000 characters term without an analysis of the sensitivity is not meaningful. For a high sensitivity the results have a large larger random part.
  3 Comments
M S
M S on 31 Oct 2011
OK, so for the big one. if I allow .01 absolute error to one parameter:
=== MATLAB ===
+0.01 = 31816475818623.8
-0.01 = 31675519324512.4
=== C++ ===
+0.01 = 31816475818623.801
-0.01 = 31675519324512.441
So I think the answer is, they are moderately unstable. But you'll notice the answers are identical. Yup, I swapped 2 very similar parameter inputs, and when I fixed the code I now get identical solutions between C++ and matlab. I am so sorry to have wasted your time!! That said, I would not have discovered this bug had I not done your sensitivity analysis, so thank you.

Sign in to comment.

More Answers (1)

James Tursa
James Tursa on 29 Oct 2011
Differences can arise from different order of operations, temporary results done in 80-bit vs 64-bit arithmetic, different rounding modes, etc, etc. As for which one is "correct", maybe neither is. Unless you examine the expression in detail to look for cancellation error etc who knows? How the heck do you expect to debug a 31000 character expression? I doubt anyone on this site will be willing to do so for you.
  2 Comments
James Tursa
James Tursa on 1 Nov 2011
Just because you copied the same expression from C++ to MATLAB does *not* guarantee that there are no order of operation differences. That was the point of my comment ... the compiler might be reordering things around without you being aware of it.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by