MathGroup Archive 2011

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Using Equal with Real Numbers

  • To: mathgroup at smc.vnet.net
  • Subject: [mg123187] Re: Using Equal with Real Numbers
  • From: A Retey <awnl at gmx-topmail.de>
  • Date: Fri, 25 Nov 2011 04:59:02 -0500 (EST)
  • Delivered-to: l-mathgroup@mail-archive0.wolfram.com
  • References: <jalb8i$s6h$1@smc.vnet.net>

Hi,

> Using statements like x1=x2, with real numbers is problematic in
> most programming languages.

Actually a single = is Set in Mathematica, what you are talking about is 
==, which is Equal or === which is SameQ.

> Below I briefly discuss an example with Mathematica and then show the
> rather truculent solution that I've come up with.
> I would love to hear your comments on this and perhaps other (likely
> better) solutions.
>
> Consider:
>
> In[187]:= list1 = Range[0, 1, 0.1]
> Out[187]= {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.}
>
> Using InputForm we see that:
>
> In[188]:= list1 // InputForm
>
> Out[188]//InputForm={0., 0.1, 0.2, 0.30000000000000004, 0.4, 0.5,
> 0.6000000000000001, 0.7000000000000001,
> 0.8, 0.9, 1.}
>
> That is, 0.3, 0.6 and 0.7 have some round-off error.
>
> Now:
>
> In[200]:= {MemberQ[list1, 0.6], MemberQ[list1, 0.7]}
> Out[200]= {True, False}
>
> (This actually depends on the OS and perhaps other things). The point is
> that he recognizes 0.6 as a member of list1 but not 0.7, even though
> both have the same InputForms.
> This issue, as you may imagine, prohibits one from using functions that
> implicitly make use of =, when dealing with real numbers.

That's not exactly true, since == will recognize the two to be equal:

Range[0, 1, 0.1][[8]] == 0.7

and even SameQ considers Real numbers to be equal if they only differ in 
their last binary digit (see the documentation of SameQ):

Range[0, 1, 0.1][[8]] === 0.7

so the problem is not Equal or even SameQ, but the pattern matcher that 
MemberQ actually usesimplicitly. The pattern matcher will obviously 
consider numbers with different binary representation to be different 
and that doesn't even make use of == or ===.

> Here is my solution:
>
> range[xi_, xf_, df_] := N@Rationalize@Range[xi, xf, df]
>
> That is, I redefine the range function. It first rationalizes the
> entries and then transform them into numeric quantities. Not only is
> this crude, but is likely quite slow for long lists. Notwithstanding, it
> does solve the problem in the previous example:
>
> In[190]:= list2 = range[0, 1, 0.1]
> Out[190]= {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.}
>
> In[191]:= list2 // InputForm
> Out[191]//InputForm= {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
> 1.}
>
> In[201]:= {MemberQ[list2, 0.6], MemberQ[list2, 0.7]}
> Out[201]= {True, True}

I don't think that it is a very useful approach to change the actual 
data when all you want is a different comparison operation. What I would 
do is something like:

list = Range[0, 1, 0.1];

MemberQ[list, _?(# == 0.7 &)]

or maybe even:

MemberQ[list, _?(Abs[#-0.7]<10^-6 &)]

with a maximal acceptable difference appropriate to the problem at hand. 
If you are wondering about the complicated patterns I suggest to learn 
about Mathematica's pattern matching. Without a proper understanding of 
pattern matching you will find Mathematica to be full of surprises and 
by far not as helpful as it could be...

hth,

albert



  • Prev by Date: Re: Root finding needs higher accuracy
  • Next by Date: Re: Root finding needs higher accuracy
  • Previous by thread: Re: Using Equal with Real Numbers
  • Next by thread: Re: Using Equal with Real Numbers