Summation Clojure Ratio Slow

I summarize a long list of odds in Clojure, something like:

(defn sum-ratios
  [n]
  (reduce
    (fn [total ind]
      (+
        total
        (/
          (inc (rand-int 100))
          (inc (rand-int 100)))))
    (range 0 n)))

Runtime for various n:

  • n = 10 ^ 4 ...... 41 ms
  • n = 10 ^ 6 ...... 3.4 s
  • n = 10 ^ 7 ...... 36 s


A (less accurate) alternative is to sum these values ​​as doubles:

(defn sum-doubles
  [n]
  (reduce
    (fn [total ind]
      (+
        total
        (double
          (/
            (inc (rand-int 100))
            (inc (rand-int 100))))))
    (range 0 n)))

Runtime for this version:

  • n = 10 ^ 4 ...... 8.8 ms
  • n = 10 ^ 6 ...... 350 ms
  • n = 10 ^ 7 ...... 3.4 s


Why is it much less to sum the coefficients? I assume this is due to finding the least common multiple of the denominators of the coefficients that are summed, but does anyone know specifically which Clojure algorithm is used to sum the coefficients?

+6
source share
1 answer

, , + Ratio s, . ​​ +:

([x y] (. clojure.lang.Numbers (add x y)))

Numbers.add(Obj, Obj):

return ops(x).combine(ops(y)).add((Number)x, (Number)y);

ops RatioOps. RatioOps.add:

final public Number add(Number x, Number y){
    Ratio rx = toRatio(x);
    Ratio ry = toRatio(y);
    Number ret = divide(ry.numerator.multiply(rx.denominator)
            .add(rx.numerator.multiply(ry.denominator))
            , ry.denominator.multiply(rx.denominator));
    return normalizeRet(ret, x, y);
}

, . BigInteger ( , , ):

(yn*xd + xn*yd) / (xd*yd)

, ; , .

, div gcd , :

static public Number divide(BigInteger n, BigInteger d){
    if(d.equals(BigInteger.ZERO))
        throw new ArithmeticException("Divide by zero");
    BigInteger gcd = n.gcd(d);
    if(gcd.equals(BigInteger.ZERO))
        return BigInt.ZERO;
    n = n.divide(gcd);
    d = d.divide(gcd);
    ...
}

gcd MutableBigInteger.

, , . ( gcd ), , .

double , FWIW, BigDecimal s.

, , . , , .

+13

All Articles