acm模板-数值计算

发布于 2021-10-18  602 次阅读


数值计算

三分(0.618法)

#define fai 0.618033988750
#define eps 1e-7
double l = minn, r = maxx;
double mid1 = l + (r - l) * (1 - fai), mid2 = l + (r - l) * fai;
while (r - l > eps) {
  if (f(mid1) > f(mid2)) {  //若函数f为先增后减的函数,则用>,反之则用<
    r = mid2;
    mid2 = mid1;
    mid1 = l + (r - l) * (1 - fai);
  } else {
    l = mid1;
    mid1 = mid2;
    mid2 = l + (r - l) * fai;
  }
}
//答案为l

牛顿迭代法(JAVA高精度开方)

public static BigInteger isqrtNewton(BigInteger n) {
  BigInteger a = BigInteger.ONE.shiftLeft(n.bitLength() / 2);
  boolean p_dec = false;
  for (;;) {
    BigInteger b = n.divide(a).add(a).shiftRight(1);
    if (a.compareTo(b) == 0 || a.compareTo(b) < 0 && p_dec)
      break;
    p_dec = a.compareTo(b) > 0;
    a = b;
  }
  return a;
}

自适应辛普森法(定积分)

double simpson(double l, double r) {
  double mid = (l + r) / 2;
  return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6;  // 辛普森公式,f为原函数
}
double asr(double l, double r, double eqs, double ans, int step) {
  double mid = (l + r) / 2;
  double fl = simpson(l, mid), fr = simpson(mid, r);
  if (abs(fl + fr - ans) <= 15 * eqs && step < 0)
    return fl + fr + (fl + fr - ans) / 15;  // 足够相似的话就直接返回
  return asr(l, mid, eqs / 2, fl, step - 1) +
         asr(mid, r, eqs / 2, fr, step - 1);  // 否则分割成两段递归求解
}
double calc(double l, double r, double eps) {
  return asr(l, r, eps, simpson(l, r), 12);
}
Hello, world!
最后更新于 2021-10-18