Re: Problem with base 2 logs and Floor

*To*: mathgroup at smc.vnet.net*Subject*: [mg73017] Re: Problem with base 2 logs and Floor*From*: Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com>*Date*: Mon, 29 Jan 2007 04:23:35 -0500 (EST)*Organization*: The Open University, Milton Keynes, UK*References*: <ephdk1$s2c$1@smc.vnet.net>

neillclift at msn.com wrote: > Hi, > > When I use an expression like this: > > r - Floor[Log[2, r]] - 1 /. r -> 4 > > I get precision errors in Mathematica 5.2. If I use an expression like > this: > > N[r - Floor[Log[2, r]] - 1] /. r -> 4 > > I get a correct result of 1 and no errors. If I use an expression like > this I get the same result: > > N[r - Ceiling[Log[2, r]] - 1] /. r -> 4 > > This is to be expected as Floor[Log[2, r]] = Ceiling[Log[2, r]] when > r is a power of two. > Unfortunatly the expessions diverge for r=8: > > N[r - Floor[Log[2, r]] - 1] /. r -> 8 gives 5 > N[r - Ceiling[Log[2, r]] - 1] /. r -> 8 gives 4 > > How can I get exacts results for expessions like this? > Thanks. > Neill. > Neill, Most of your troubles come from evaluation order of the components of the expressions. We will investigate first the evaluation order of the transformation rules and how to fix it, then an alternative solution, shorter and using SetDelayed, will be giving at the bottom of this mail. Note that using machine size numbers in the transformation rule yields the same result than using the N[] function. (Floor does not attempt any symbolic simplification.) In[1]:= r - Floor[Log[2, r]] - 1 /. r -> 4. Out[1]= 1. Now, if you compute directly log_2(4), Mathematica returns the simplified answer 2. In[2]:= Log[2, 4] Out[2]= 2 In this case, Floor has no problem to determine the correct ans exact result. In[3]:= Floor[Log[2, 4]] Out[3]= 2 However, things behave differently when you apply some transformation rules. In[4]:= Log[2, r] /. r -> 4 Out[4]= Log[4] ------ Log[2] The above expression is returned because Mathematica standardizes the logarithm first. In[5]:= Trace[Log[2, r] /. r -> 4] Out[5]= Log[r] Log[r] Log[r] Log[4] {{Log[2, r], ------, ------}, ------ /. r -> 4, ------} Log[2] Log[2] Log[2] Log[2] After the rule has been applied, no other transformations or simplifications are used. One way to force Mathematica to simplify the ration of logarithms is to use FullSimplify. In[6]:= FullSimplify[Log[4]/Log[2], ComplexityFunction -> (Count[{#1}, _Log, Infinity] & )] Out[6]= 2 However, if we plug directly the above expression into our original expression, no simplification seems to happen anymore! In[7]:= r - Floor[FullSimplify[Log[2, r], ComplexityFunction -> (Count[{#1}, _Log, Infinity] & )]] - 1 /. r -> 8 Floor::"meprec" : "Internal precision limit $MaxExtraPrecision = 49.99999999999999` reached while evaluating Floor[Log[8]\Log[2]]." Out[7]= Log[8] 7 - Floor[------] Log[2] The issue is, again, a matter of precedence: if we use Hold and ReleaseHold, we get the correct answer. In[8]:= ReleaseHold[ r - Floor[Hold[FullSimplify[Log[2, r], ComplexityFunction -> (Count[{#1}, _Log, Infinity] & )]]] - 1 /. r -> 8] Out[8]= 4 In[9]:= ReleaseHold[ r - Ceiling[Hold[FullSimplify[Log[2, r], ComplexityFunction -> (Count[{#1}, _Log, Infinity] & )]]] - 1 /. r -> 8] Out[9]= 4 Indeed, we can get ride of FullSimplify, and and wrap Hold around the original expression (not including the transformation rule) and ReleaseHold around the whole thing. In[10]:= ReleaseHold[Hold[r - Floor[Log[2, r]] - 1] /. r -> 8] Out[10]= 4 In[11]:= ReleaseHold[Hold[r - Ceiling[Log[2, r]] - 1] /. r -> 8] Out[11]= 4 Finally, an easier way is to define a new function with SetDelayed. In doing so, the internal expression is kept as it is written until the function is called. Then, the argument is first replace within the body of the function, then the resulting expression is simplified and evaluated. In[12]:= floorlog[r_] := r - Floor[Log[2, r]] - 1 ceilinglog[r_] := r - Ceiling[Log[2, r]] - 1 In[14]:= floorlog[8] Out[14]= 4 In[15]:= ceilinglog[8] Out[15]= 4 Regards, Jean-Marc