Re: Using ReplaceAll (/.) on numerical digits
- To: mathgroup at smc.vnet.net
- Subject: [mg113274] Re: Using ReplaceAll (/.) on numerical digits
- From: Bill Rowe <readnews at sbcglobal.net>
- Date: Thu, 21 Oct 2010 07:03:56 -0400 (EDT)
On 10/20/10 at 4:10 AM, rklopp at exponent.com (Richard Klopp) wrote: >Background: I made some lab measurements and then calibrated the >test instrument after the fact. This changed the measurements >slightly. I wanted to replace the measurements with the calibrated >values. The measurements were all very close to 0.5600, only >differing in the thousandths and ten-thousandths places, so I coded >my original data as a list of two-digit integers {20,30,40}, then >divided the whole list by 10000 and added 0.5600 to it. >I found some seemingly weird behavior with ReplaceAll as shown >below. Note how 0.563 in data remains untouched while 0.562 and >0.564 get replaced as intended, but when I simply type in 0.563 and >do a replace, it gets replaced successfully. Can someone explain why >this happens? >data = 0.5600 + 1/10000 {20, 30, 40} {0.562, 0.563, 0.564} >data /. {0.562 -> 0.5622, 0.563 -> 0.5637, 0.564-> 0.5641} >{0.5622, 0.563, 0.5641} (* 0.563 stays untouched *) To me, the surprising thing isn't that 0.563 wasn't changed but that 0.564 was changed. The key to understanding what happens with ReplaceAll is use FullForm to see what Mathematica is using to represent the number. That is: In[8]:= data // FullForm Out[8]//FullForm= List[0.562`,0.5630000000000001`,0.5640000000000001`] As you can see, there is an extra digit for both of the last values. This is not an uncommon occurrence since most values of the form .xxx will not have a finite representation in binary. Consequently, the nearest machine number to what you input will generally not be exactly what you entered. Looking at the FullForm of the replacement list In[9]:= {0.562 -> 0.5622, 0.563 -> 0.5637, 0.564 -> 0.5641} // FullForm Out[9]//FullForm= List[Rule[0.562`,0.5622`],Rule[0.563`,0.5637`],Rule[0.564`,0.5641`]] you can see there is no match. You found one way to circumvent the issue of machine numbers not being exactly what you enter. Another way would be to use Rationalize to convert the machine values to exact values. For example, In[10]:= Rationalize[data] /. Thread[Rationalize[{0.562, 0.563, 0.564}] -> {0.5622, 0.5637, 0.5641}] Out[10]= {0.5622,0.5637,0.5641} In essence, I am using Rationalize to serve the same purpose as converting things to a string. I ensure both the thing to be replaced and the rule defining the thing to be replaced have the same form and match so that the replacement occurs as desired.