栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

(a * b)/ c MulDiv并处理中间乘法的溢出

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

(a * b)/ c MulDiv并处理中间乘法的溢出

我一直在尝试一种方法(1)进行乘法运算,

a
b
使用21位四肢上的school算法(2)进行长除法运算,并使用a
来存储高阶位
c
的残差的不寻常表示形式并存储低位。我不知道是否可以与标准的长距离比赛竞争,但是为了您的享受,
a*b -c*q``double``long

public class MulDiv {  public static void main(String[] args) {    java.util.Random r = new java.util.Random();    for (long i = 0; true; i++) {      if (i % 1000000 == 0) {        System.err.println(i);      }      long a = r.nextLong() >> (r.nextInt(8) * 8);      long b = r.nextLong() >> (r.nextInt(8) * 8);      long c = r.nextLong() >> (r.nextInt(8) * 8);      if (c == 0) {        continue;      }      long x = mulDiv(a, b, c);      java.math.BigInteger aa = java.math.BigInteger.valueOf(a);      java.math.BigInteger bb = java.math.BigInteger.valueOf(b);      java.math.BigInteger cc = java.math.BigInteger.valueOf(c);      java.math.BigInteger xx = aa.multiply(bb).divide(cc);      if (java.math.BigInteger.valueOf(xx.longValue()).equals(xx) && x != xx.longValue()) {        System.out.printf("a=%d b=%d c=%d: %d != %sn", a, b, c, x, xx);      }    }  }  // Returns truncate(a b/c), subject to the precondition that the result is  // defined and can be represented as a long.  private static long mulDiv(long a, long b, long c) {    // Decompose a.    long a2 = a >> 42;    long a10 = a - (a2 << 42);    long a1 = a10 >> 21;    long a0 = a10 - (a1 << 21);    assert a == (((a2 << 21) + a1) << 21) + a0;    // Decompose b.    long b2 = b >> 42;    long b10 = b - (b2 << 42);    long b1 = b10 >> 21;    long b0 = b10 - (b1 << 21);    assert b == (((b2 << 21) + b1) << 21) + b0;    // Compute a b.    long ab4 = a2 * b2;    long ab3 = a2 * b1 + a1 * b2;    long ab2 = a2 * b0 + a1 * b1 + a0 * b2;    long ab1 = a1 * b0 + a0 * b1;    long ab0 = a0 * b0;    // Compute a b/c.    DivBy d = new DivBy(c);    d.shift21Add(ab4);    d.shift21Add(ab3);    d.shift21Add(ab2);    d.shift21Add(ab1);    d.shift21Add(ab0);    return d.getQuotient();  }}public strictfp class DivBy {  // Initializes n <- 0.  public DivBy(long d) {    di = d;    df = (double) d;    oneOverD = 1.0 / df;  }  // Updates n <- 2^21 n + i. Assumes |i| <= 3 (2^42).  public void shift21Add(long i) {    // Update the quotient and remainder.    q <<= 21;    ri = (ri << 21) + i;    rf = rf * (double) (1 << 21) + (double) i;    reduce();  }  // Returns truncate(n/d).  public long getQuotient() {    while (rf != (double) ri) {      reduce();    }    // Round toward zero.    if (q > 0) {      if ((di > 0 && ri < 0) || (di < 0 && ri > 0)) {        return q - 1;      }    } else if (q < 0) {      if ((di > 0 && ri > 0) || (di < 0 && ri < 0)) {        return q + 1;      }    }    return q;  }  private void reduce() {    // x is approximately r/d.    long x = Math.round(rf * oneOverD);    q += x;    ri -= di * x;    rf = repairLowOrderBits(rf - df * (double) x, ri);  }  private static double repairLowOrderBits(double f, long i) {    int e = Math.getExponent(f);    if (e < 64) {      return (double) i;    }    long rawBits = Double.doubleToRawLongBits(f);    long lowOrderBits = (rawBits >> 63) ^ (rawBits << (e - 52));    return f + (double) (i - lowOrderBits);  }  private final long di;  private final double df;  private final double oneOverD;  private long q = 0;  private long ri = 0;  private double rf = 0;}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/485577.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号