java中的快速正弦和余弦函数

use*_*974 4 java optimization trigonometry

我知道这些Math.sin()Math.cos()功能,但我想知道是否有一种方法可以创建(或使用已经存在的)更快的功能,因为我不关心精确定位.我正在寻求执行基本的sin或cos计算,并使其基本上尽可能快地执行.简单地迭代西格玛几次比任何更快Math.sin()

ary*_*naq 7

由于你不太关心准确性将它存储在一个预计算或只计算过一次的表中,这就是我想要避免调用Math时所做的事情.

大致

public class CosSineTable {
double[] cos = new double[361];
double[] sin = new double[361];
private static CosSineTable table = new CosSineTable();

private CosSineTable() {
    for (int i = 0; i <= 360; i++) {
        cos[i] = Math.cos(Math.toRadians(i));
        sin[i] = Math.sin(Math.toRadians(i));
    }
}

public double getSine(int angle) {
    int angleCircle = angle % 360;
    return sin[angleCircle];
}

public double getCos(int angle) {
    int angleCircle = angle % 360;
    return cos[angleCircle];
}

public static CosSineTable getTable() {
    return table;
}
}
Run Code Online (Sandbox Code Playgroud)

我将循环和方法的优化留给您.

  • Aye只需要为负数返回-sin [angle],cos是相同的. (2认同)

may*_*Van 6

预先计算的表格是要走的路.这是一个实现:

static final int precision = 100; // gradations per degree, adjust to suit

static final int modulus = 360*precision;
static final float[] sin = new float[modulus]; // lookup table
static { 
    // a static initializer fills the table
    // in this implementation, units are in degrees
    for (int i = 0; i<sin.length; i++) {
        sin[i]=(float)Math.sin((i*Math.PI)/(precision*180));
    }
}
// Private function for table lookup
private static float sinLookup(int a) {
    return a>=0 ? sin[a%(modulus)] : -sin[-a%(modulus)];
}

// These are your working functions:
public static float sin(float a) {
    return sinLookup((int)(a * precision + 0.5f));
}
public static float cos(float a) {
    return sinLookup((int)((a+90f) * precision + 0.5f));
}
Run Code Online (Sandbox Code Playgroud)

在我的笔记本电脑上,这些速度比它快6倍Math.sin.

我只使用了一张表 - 将余弦变成正弦的成本并不是真正可辨别的.

我使用浮动,假设你可能会在计算中使用浮点数,因为你对性能的偏好超过了精度.这里没有太大区别,因为瓶颈实际上只是数组查找.

这是我的基准:

public static void main(String[] args) {
    int reps = 1<<23;
    int sets = 4;

    Q.pl("  Trial  sinTab  cosTab  sinLib");
    for(int i = 0; i<sets; i++) {
        Q.pf("%7d\t%7.2f\t%7.2f\t%7.2f\n", i, testSinTab(reps), testCosTab(reps), testSinLib(reps));
    }
}

private static float[] sample(int n) {
    Random rand = new Random();
    float[] values = new float[n];
    for (int i=0; i<n; i++) {
        values[i] = 400*(rand.nextFloat()*2-1);
    }
    return values;
}
private static float testSinTab(int n) {
    float[] sample = sample(n);
    long time = -System.nanoTime();
    for (int i=0; i<n; i++) {
        sample[i] = sin(sample[i]);
    }
    time += System.nanoTime();
    return (time/1e6f);
}
private static float testCosTab(int n) {
    float[] sample = sample(n);
    long time = -System.nanoTime();
    for (int i=0; i<n; i++) {
        sample[i] = cos(sample[i]);
    }
    time += System.nanoTime();
    return time/1e6f;
}
private static float testSinLib(int n) {
    float[] sample = sample(n);
    long time = -System.nanoTime();
    for (int i=0; i<n; i++) {
        sample[i] = (float) Math.sin(sample[i]);
    }
    time += System.nanoTime();
    return time/1e6f;
}
Run Code Online (Sandbox Code Playgroud)

输出:

  Trial  sinTab  cosTab  sinLib
      0  102.51  111.19  596.57
      1   93.72   92.20  578.22
      2  100.06  107.20  600.68
      3  103.65  102.67  629.86
Run Code Online (Sandbox Code Playgroud)