MathGroup Archive 2013

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

Search the Archive

Re: Round-off error?

  • To: mathgroup at smc.vnet.net
  • Subject: [mg131932] Re: Round-off error?
  • From: Itai Seggev <itais at wolfram.com>
  • Date: Sat, 2 Nov 2013 02:25:43 -0400 (EDT)
  • Delivered-to: l-mathgroup@mail-archive0.wolfram.com
  • Delivered-to: l-mathgroup@wolfram.com
  • Delivered-to: mathgroup-outx@smc.vnet.net
  • Delivered-to: mathgroup-newsendx@smc.vnet.net
  • References: <20131031034715.CCF8C6A6B@smc.vnet.net>

> Hi everyone,
>
> The following lines of code are stumping me.
>
> ClearAll[y]
> dt = 0.15;
> Do[y[i*dt] = "hi there", {i, 0, 20}]
> Table[{i, y[(i + 1)*dt], y[i*dt + dt]}, {i, 0, 19}]
>
> Here is the output:
>
> 0	hi there	hi there
> 1	hi there	hi there
> 2	hi there	hi there
> 3	hi there	hi there
> 4	hi there	hi there
> 5	hi there	y(0.9)
> 6	hi there	y(1.05)
> 7	hi there	hi there
> 8	hi there	hi there
> 9	hi there	hi there
> 10	hi there	hi there
> 11	hi there	hi there
> 12	hi there	y(1.95)
> 13	hi there	hi there
> 14	hi there	hi there
> 15	hi there	hi there
> 16	hi there	hi there
> 17	hi there	hi there
> 18	hi there	y(2.85)
> 19	hi there	hi there
>
>
> It seems that y[i*dt+dt] does not match y[(i+1)*dt], perhaps due to
> numerical round-off?  If you switch to dt=15/100, the problem goes away. 
> You might also try different values for dt to see what happens.
>
>
> If it is numerical round-off, then why does this evaluate to true?
>
> 6*.15 == 5*.15 + .15
> True

The first thing to do whenever Mathematica does something unexpected is to look 
at the FullForm. 

In[1]:= 6*.15 //FullForm
Out[1]//FullForm= 0.8999999999999999`

In[2]:= 5*.15 + .15 //FullForm
Out[2]//FullForm= 0.9`

So clearly these are two different numbers.  And the answer to your last 
question is easy--Equal by default ignores the last seven bits in comparison, 
pricesly to avoid too many False due to machine precision error.  You can 
control this using the variable Internal`$EqualTolerance:

In[3]:= Block[{Internal`$EqualTolerance = 0}, 6*.15 == 5*.15 + .15]

Out[3]= False

Note that this variable is specified using decimal digits, which is why its 
default value is 2.10721 == N[Log[10, 2^7].

It's also easy to understand why it goes away with 15/100--you're now using 
exact numbers and you end up with the exact result 9/10 in both cases.

However, you have an added twist, which is that you're using a function 
definition / pattern.  (And this is something I didn't fully understand until I 
started poking at this, so thanks for the good question!) All patterns, 
including literal patterns like 0.9`, are hashed for efficiency reasons.  On 
the other hand Equal is no longer strickly transitive (since two numbers which 
different from a third by 6 bits need not differ from each other by less than 
7). So machine numbers are effectively binned in the hash process to provide 
something fast and transitive.  You are suffereing because sometimes the two 
computations are in the same bin and sometimes they are not. 

In[31]:= Internal`HashSameQ[.15*6, .15*5 + .15]
Out[31]= False

In[32]:= Internal`HashSameQ[.15*5, .15*4 + .15]
Out[32]= True

This binning only affects patterns/definitions tied to specific approximate 
numbers.  If you want to avoid the binning, you could rewrite your definition 
in the form

y[x_] /; x == num = "Hi there"

This will make sure that two numbers which are Equal trigger the same 
definition, but at performance cost.  How to balance those is dependent on your 
needs and preferences.

Here I show that this change actually works.  Notice that I'm using With in the 
Do loop to make sure that num is evaluated before the definition of y is 
created, which is necessary when generating definitions programmatically. 

In[27]:= ClearAll[y]
dt=0.15;
Do[With[{num=dt*i}, y[x_] /; x==num="hi there"],{i,0,20}]
Table[{i,y[(i+1)*dt],y[i*dt+dt]},{i,0,19}]//TableForm
Out[30]//TableForm= 
0	hi there	hi there
1	hi there	hi there
2	hi there	hi there
3	hi there	hi there
4	hi there	hi there
5	hi there	hi there
6	hi there	hi there
7	hi there	hi there
8	hi there	hi there
9	hi there	hi there
10	hi there	hi there
11	hi there	hi there
12	hi there	hi there
13	hi there	hi there
14	hi there	hi there
15	hi there	hi there
16	hi there	hi there
17	hi there	hi there
18	hi there	hi there
19	hi there	hi there


-- 
Itai

Itai Seggev
Mathematica Algorithms R&D



  • Next by Date: Re: Round-off error?
  • Next by thread: Re: Round-off error?