Clean up Rational and add precision parameter to truncation methods

I originally meant to only implement missing precision parameters to a few `Rational` methods (ceil, floor, and truncate) but ended up cleaning up the entire Rational class along with it.

There are general speedups throughout, particularly rounding. Some numbers:

Before

         +(Rational)  1634641.1 (±1.5%) i/s -    8169000 in   4.998690s
          +(Integer)  1291407.0 (±1.9%) i/s -    6485635 in   5.024185s
            +(Float)  1465402.3 (±0.8%) i/s -    7341756 in   5.010369s
         rationalize   381928.8 (±1.3%) i/s -    1920732 in   5.029955s
               round   355498.0 (±1.3%) i/s -    1795945 in   5.052845s
            round(2)   335405.7 (±1.3%) i/s -    1687754 in   5.032853s
            truncate  5514276.3 (±0.9%) i/s -   27778542 in   5.038035s
         truncate(2)  N/A

After

         +(Rational)  1882125.4 (±1.5%) i/s -    9422304 in   5.007394s
          +(Integer)  1281896.1 (±1.2%) i/s -    6422220 in   5.010740s
            +(Float)  2083774.1 (±0.8%) i/s -   10418824 in   5.000301s
         rationalize   735087.0 (±1.0%) i/s -    3721465 in   5.063188s
               round  4864552.6 (±1.4%) i/s -   24370422 in   5.010775s
            round(2)  1064418.3 (±0.8%) i/s -    5330724 in   5.008434s
            truncate  5534497.7 (±0.9%) i/s -   27891990 in   5.040073s
         truncate(2)  1146689.3 (±0.9%) i/s -    5788380 in   5.048281s