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