Skip to main content
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

Mathematica tries to be helpful and equality comparisons have some tolerance. This can be controlled by Internal`$EqualToleranceThis can be controlled by Internal`$EqualTolerance, which is set to 7 binary digits by default.

Mathematica tries to be helpful and equality comparisons have some tolerance. This can be controlled by Internal`$EqualTolerance, which is set to 7 binary digits by default.

Mathematica tries to be helpful and equality comparisons have some tolerance. This can be controlled by Internal`$EqualTolerance, which is set to 7 binary digits by default.

added 324 characters in body
Source Link
Szabolcs
  • 236.5k
  • 31
  • 641
  • 1.3k
Det[{{a, b}, {b, d}}]
(* -b^2 + a d *)

% /. N[{a -> -1, b -> -5/2, d -> -25/4}, 10]
(* 0.*10^-9 *)

Precision[%]Accuracy[%]
(* 08.60206 *)

%% == 0
(* True *)

The result is zero, but it has no precision left in itlost some accuracy. The zero comparison is acceptedevaluates to (for better or worse)True.

Det@N[{{-1, -5/2}, {-5/2, -25/4}}, 10]
(* -1.469367939*10^-38 *)

{Accuracy[%], Precision[%]}
(* {47.8329, 10.} *)

Note that we have both Precision and Accuracy in Mathematica. The former is a relative measure, the latter an absolute one. Since Precision is a relative measure, it is less meaningful with a zero result.

Det[{{a, b}, {b, d}}]
(* -b^2 + a d *)

% /. N[{a -> -1, b -> -5/2, d -> -25/4}, 10]
(* 0.*10^-9 *)

Precision[%]
(* 0. *)

%% == 0
(* True *)

The result is zero, but it has no precision left in it. The zero comparison is accepted (for better or worse).

Det@N[{{-1, -5/2}, {-5/2, -25/4}}, 10]
(* -1.469367939*10^-38 *)

Precision[%]
(* 10. *)
Det[{{a, b}, {b, d}}]
(* -b^2 + a d *)

% /. N[{a -> -1, b -> -5/2, d -> -25/4}, 10]
(* 0.*10^-9 *)

Accuracy[%]
(* 8.60206 *)

%% == 0
(* True *)

The result is zero, but it has lost some accuracy. The zero comparison evaluates to True.

Det@N[{{-1, -5/2}, {-5/2, -25/4}}, 10]
(* -1.469367939*10^-38 *)

{Accuracy[%], Precision[%]}
(* {47.8329, 10.} *)

Note that we have both Precision and Accuracy in Mathematica. The former is a relative measure, the latter an absolute one. Since Precision is a relative measure, it is less meaningful with a zero result.

Source Link
Szabolcs
  • 236.5k
  • 31
  • 641
  • 1.3k

It is a well known problem of floating point arithmetic that equality comparisons are unreliable. For example if you try

1.0 == 0.3 + 0.3 + 0.3 + 0.1

in Python or C or any other traditional language, you get false. Why? Because these numbers are not exactly representable in binary the same way as $1/3 = 0.33333333\dots$ is not exactly representable in decimal using a finite number of digits. Due to this, and potentially due to numerical roundoff errors the two sides won't be digit-for-digit equal up to the last binary digit.

You are probably aware of this.

Now try in Mathematica:

In[151]:= 1.0 == 0.3 + 0.3 + 0.3 + 0.1
Out[151]= True

Mathematica tries to be helpful and equality comparisons have some tolerance. This can be controlled by Internal`$EqualTolerance, which is set to 7 binary digits by default.

Internal`$EqualTolerance
(* 2.10721 *)

Log[2, 10^Internal`$EqualTolerance]
(* 7. *)

This choice of 7 digits is of course rather arbitrary and even though equality comparisons behave in a nice and convenient way most of the time, you must keep in mind that they are not foolproof, and cannot be foolproof even in principle.

The difficulty is that your determinant is zero:

Det@N[{{-1, -5/2}, {-5/2, -25/4}}]
(* 3.46945*10^-16 *)

When saying "equal except for the last 7 binary digits" (or $\sim 2.1$ decimal digits), we are talking about a relative tolerance. Relative tolerances don't really work for zero values because we can't divide by zero. Or rather: since floating point numbers are stored as a separate exponent and mantissa, once the result is zero, the last few normally insignificant mantissa digits are shifted up into positions which appear significant.

People have already pointed out Chop, which deals exactly with this problem. It converts floating point numbers smaller than a certain threshold ($10^{-10}$ by default) into exact 0. I.e. it uses an absolute tolerance, not a relative one.

Another way to deal with it is to use Mathematica's arbitrary precision inexact numbers instead of machine precision numbers. The former have built-in precision tracking, so the system can detect that a zero that arises due to catastrophic cancellation has very few accurate digits. This is also not foolproof, but it's much better than no precision tracking at all. Arbitrary precision numbers can be forced by SetPrecision or by using N with a second argument on exact numbers. Observe:

Det[{{a, b}, {b, d}}]
(* -b^2 + a d *)

% /. N[{a -> -1, b -> -5/2, d -> -25/4}, 10]
(* 0.*10^-9 *)

Precision[%]
(* 0. *)

%% == 0
(* True *)

The result is zero, but it has no precision left in it. The zero comparison is accepted (for better or worse).

Unfortunately, when using Det directly on such an arbitrary precision matrix, it doesn't perform the precision tracking:

Det@N[{{-1, -5/2}, {-5/2, -25/4}}, 10]
(* -1.469367939*10^-38 *)

Precision[%]
(* 10. *)