mathpack numeric literals preface

In a very heated situation you have to go even further with golfing. 
(e.g. in a challenge where your answer is 100 characters long and it is just embarrassing that you couldn't make it 99)
In that case, from now on you use the winner's algorithm of this challenge :)

goal

You have to write a program that takes an uint32 and returns the most compressed form.

$ mathpack 147456
9&lt;&lt;14



There will be multiple solutions for a number. Pick the shortest one
If the compressed form is longer or equal to the original number, return the original number


rules


write in any language - output in any language 
i'm aware of that in C 'abc' is 6382179 and you can achieve pretty good results with this conversion. but languages are separated in this challenge so don't lose heart
it is prohibited to use external variables. only operators and literals and math related functions!


scoring

here are the test cases: pastebin.com/0bYPzUhX
your score (percent) will be the ratio of byte_size_of_your_output / byte_size_of_the_list without line breaks.
(you have to do this by yourself as i'll just verify the best codes just in case)
winners will be chosen by score and language of output!

examples:

$ mathpack 147456 | mathpack 97787584 |  mathpack 387420489
            9&lt;&lt;14 |           9e7^9e6 |            pow(9,9)
Code: Mathematica, Output: Julia, ~98.9457% (20177/20392 bytes)

optimise[n_] := 
  Module[{bits, trimmedBits, shift, unshifted, nString, versions, 
    inverted, factorised, digits, trimmedDigits, exponent, base, 
    xored, ored, anded},
   nString = ToString@n;
   versions = {nString};

   (* Try bitshifting *)
   bits = IntegerDigits[n, 2];
   trimmedBits = bits /. {x___, 1, 0 ..} :&gt; {x, 1};
   shift = ToString[Length[bits] - Length[trimmedBits]];
   unshifted = ToString@FromDigits[trimmedBits, 2];
   AppendTo[versions, unshifted &lt;&gt; "&lt;&lt;" &lt;&gt; shift];

   (* Try inverting *)
   inverted = ToString@FromDigits[1 - PadLeft[bits, 32], 2];
   AppendTo[versions, "~" &lt;&gt; inverted];

   (* Try invert/shift/invert *)
   trimmedBits = bits /. {x___, 0, 1 ..} :&gt; {x, 1};
   shift = ToString[Length[bits] - Length[trimmedBits]];
   unshifted = ToString@FromDigits[trimmedBits, 2];
   AppendTo[versions, "~(~" &lt;&gt; unshifted &lt;&gt; "&lt;&lt;" &lt;&gt; shift &lt;&gt; ")"];

   (* Try factoring *)
   factorised = Riffle[
      FactorInteger[n]
        /. {a_, 1} :&gt; ToString@a
       /. {a_Integer, b_Integer} :&gt; ToString[a] &lt;&gt; "^" &lt;&gt; ToString[b]
      , "+"] &lt;&gt; "";
   AppendTo[versions, factorised];

   (* Try scientific notation *)
   digits = IntegerDigits[n, 10];
   trimmedDigits = digits /. {x___, d_ /; d &gt; 0, 0 ..} :&gt; {x, d};
   exponent = ToString[Length[digits] - Length[trimmedDigits]];
   base = ToString@FromDigits[trimmedDigits, 10];
   AppendTo[versions, base &lt;&gt; "e" &lt;&gt; exponent];

   (* Don't try hexadecimal notation. It's never shorter for 32-bit uints. *)
   (* Don't try base-36 or base-62, because parsing those requires 12 characters for
      parseint("...") *)

   SortBy[versions, StringLength][[1]]
  ];

mathpack[n_] := 
 Module[{versions, increments},
  increments = Range@9;
  versions = Join[
    optimise[#2] &lt;&gt; "+" &lt;&gt; ToString@# &amp; @@@ ({#, n - #} &amp;) /@ 
      Reverse@increments,
    {optimise@n},
    optimise[#2] &lt;&gt; "-" &lt;&gt; ToString@# &amp; @@@ ({#, n + #} &amp;) /@ 
      increments,
    optimise[#2] &lt;&gt; "*" &lt;&gt; ToString@# &amp; @@@ 
      Cases[({#, n / #} &amp;) /@ increments, {_, _Integer}],
    optimise[#2] &lt;&gt; "/" &lt;&gt; ToString@# &amp; @@@ ({#, n * #} &amp;) /@ 
      increments
    ];
  SortBy[versions, StringLength][[1]]
 ];


The function takes a number and returns the shortest string it finds. Currently it applies four simple optimisations (I might add more tomorrow).

You can apply it to the entire file (to measure its score) as follows:

input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output &lt;&gt; ""]/StringLength[input &lt;&gt; ""]]


Note that some of these optimisations assume that you're on a 64-bit Julia, such that integer literals give you an int64 by default. Otherwise, you'll be overflowing anyway for integers greater than 231. Using that assumption we can apply a few optimisations whose intermediate steps are actually even larger than 232. 

EDIT: I added the optimisation suggested in the OP's examples to bitwise xor two large numbers in scientific notation (actually, for all of xor, or and and). Note that extending the xormap, ormap and andmap to include operands beyond 232 might help finding additional optimisations, but it doesn't work for the given test cases and only increases run time by something like a factor of 10.

EDIT: I shaved off another 16 bytes, by checking all n-9, n-8, ..., n+8, n+9 for whether any of those can be shortened, in which case I represented the number based on that, adding or subtracting the difference. There are a few cases, where one of those 18 numbers can be represented with 3 or more characters less than n itself, in which case I can make some extra savings. It takes about 30 seconds now to run it on all test cases, but of course, if someone actually "used" this function, he'd only run it on a single number, so it's still well under a second.

EDIT: Another incredible 4 bytes by doing the same for multiplication and division. 50 seconds now (the divided ones don't take as long, because I'm only checking these if the number is actually divisible by the factor of interest).

EDIT: Another optimisation that doesn't actually help with the given test set. This one could save a byte for things like 230 or 231. If we had uint64s instead, there'd be a lot of numbers where this could be a huge saving (basically, whenever the bit representation ends in a lot of 1s).

EDIT: Removed the xor, or, and optimisations altogether. I just noticed they don't even work in Julia, because (quite obviously) scientific notation gives you a float where bit-wise operators are not even defined. Interestingly, one or more of the newer optimisations seem to catch all of the cases that were shortened by these optimisations, because the score didn't change at all.