11
$\begingroup$

I wish to display logarithms with different bases in the single-term rather than numerator/denominator form during output:

Log[17]/Log[2]   ->  Log2[17]
Log[13]/Log[10]  ->  Log10[13]
Log[99]/Log[11]  ->  Log[11, 99]

What is the best way to apply formatting rules like this?

$\endgroup$
5
  • $\begingroup$ Note: this Q&A is intended both to instruct and to solicit alternative methods or refinements of methods shown. $\endgroup$
    – Mr.Wizard
    Jul 1, 2012 at 10:18
  • $\begingroup$ Wouldn't a requirement to have all output in the same base (that you globally set) be a more natural one? So that Log10[2] + Log[5] automatically converts to 1/Log2[10] + Log2[5]/Log2[E] if you're a CS person? $\endgroup$ Jul 1, 2012 at 11:50
  • $\begingroup$ @Sjoerd again that's not what I'm going for here but feel free to post an answer to that effect if you want. :-) $\endgroup$
    – Mr.Wizard
    Jul 1, 2012 at 12:16
  • $\begingroup$ Never had that requirement, so that would go against the FAQ (asking questions about problems you actually face). :-P $\endgroup$ Jul 1, 2012 at 12:37
  • $\begingroup$ Well, Log[17]/Log[2] is a problem I actually face: seeing that kind of output annoys me as I compulsively want to shorten it. :^) $\endgroup$
    – Mr.Wizard
    Jul 1, 2012 at 12:55

2 Answers 2

11
$\begingroup$

One can use $PrePrint and ReplaceAll to effect this:

$PrePrint = # /. {
     Log[n_]/Log[2]  :> Defer @ Log2[n],
     Log[n_]/Log[10] :> Defer @ Log10[n],
     Log[n_]/Log[b_] :> Defer @ Log[b, n]
     } &;

Or MakeBoxes:

MakeBoxes[Log[n_]/Log[2], fmt_]  := ToBoxes[Defer @ Log2[n], fmt]
MakeBoxes[Log[n_]/Log[10], fmt_] := ToBoxes[Defer @ Log10[n], fmt]
MakeBoxes[Log[n_]/Log[b_], fmt_] := ToBoxes[Defer @ Log[b, n], fmt]

It is also possible to use Format but in this case it requires unprotecting Times:

Unprotect[Times];

Format[Log[n_]/Log[2]]  := Defer @ Log2[n]
Format[Log[n_]/Log[10]] := Defer @ Log10[n]
Format[Log[n_]/Log[b_]] := Defer @ Log[b, n]

Protect[Times];

These assignments are made to a special class of rules: FormatValues. Because these are only used in formatting this should not slow down internal operations using Times, unlike overloading UpValues or DownValues.

Each method relies on Defer to prevent an infinite recursion yet allow evaluation of output when it is given as input.

Result:

Mathematica graphics

$\endgroup$
5
  • $\begingroup$ What about (Log[17] + Log[4])/Log[10]? $\endgroup$ Jul 1, 2012 at 11:49
  • $\begingroup$ @Sjoerd I'm not attempting that kind of operation but Simplify takes care of that particular case. $\endgroup$
    – Mr.Wizard
    Jul 1, 2012 at 12:14
  • $\begingroup$ I know that, of course. The point that I wanted to make is that the precise configuration of Logs that you want to replace will more often than not be hidden somewhere in the structure of your output. Your current answer falls short of handling that. $\endgroup$ Jul 1, 2012 at 12:35
  • $\begingroup$ @Sjoerd That's true. Nevertheless it makes for cleaner output in many cases. I am open to improvements. :-) $\endgroup$
    – Mr.Wizard
    Jul 1, 2012 at 12:53
  • 6
    $\begingroup$ I have the solution but the margin of my laptop is too small to contain it. $\endgroup$ Jul 1, 2012 at 13:33
4
$\begingroup$

Using a trick similar to what Chip showed in this answer:

SetSystemOptions["SimplificationOptions" -> "AutosimplifyTwoArgumentLog" -> False];

logRule = Log[x_]/Log[b_] :> Switch[b, 2, Log2[x], 10, Log10[x], _, Log[b, x]];

{Log[17]/Log[2], Log[13]/Log[10], Log[99]/Log[11]} /. logRule
   {Log2[17], Log10[13], Log[11, 99]}

Sjoerd's example in a comment to the Wizard's answer requires some finesse:

Expand[(Log[17] + Log[4])/Log[10]] /. logRule
   Log10[4] + Log10[17]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.