窦功能的实现|计算时间

时间:2019-01-26 16:56:28

标签: java

有人可以告诉我为什么此代码不起作用吗?我正在尝试以给定的精度限制实现正弦函数(通过误差变量)。

此处提供了有关计算的某些详细信息:https://en.wikipedia.org/wiki/Taylor_series

berechnePot计算效能 berechneFak计算师资 berechneVZW计算前置符号(正负)

enter image description here

我不明白为什么函数要计算的这么慢。

public class Sinus {

    public static double sinus(double x) {
        double error = 0.001;

        double summand = 0;
        double sum = 0;

        int k = 0;
        do {
            double pot = 0;
            double fak = 0;
            pot = berechnePot(x, k);
            fak = berechneFak(k);
            summand = pot / fak;
            berechneVZW(summand, k);
            sum += summand;

            k++;
        } while (abs(summand) > error);
        return sum;
    }

    public static double abs(double value) {
        if (value < 0) return -value;
        else return value;
    }

    public static double berechneVZW(double value, int k) {
        if (k % 2 == 0) {
            return value;
        } else {
            return value *= (-1);
        }
    }

    public static double berechnePot(double x, double k) {
        double pot = 0;
        pot += x;
        for (int i = 0; i <= k; i++) {
            pot *= (x * x);
        }
        return pot;
    }

    public static double berechneFak(int k) {
        double fak = 1;
        if (k == 0) {
            return 1;
        } else {
            for (int i = 0; i <= k; k++) {
                fak *= (2 * i + 1);
            }
        }
        return fak;

    }
}

最后我找到了正确的解决方案。

我希望新的结构可以帮助您更好地理解我的实现。

感谢您的所有帮助!

public class Sinus {

public static double sinus(double x) {
    double error = 0.00001;

    double summand = 0;
    double result = 0;
    double fak = 0;

    int k = 0;
    do {
        double pot = 0;
        pot = calcNumeratorPotency(x, k);
        fak = calcDenumeratorFaculty(k);
        summand = pot / fak;
        summand = definePreSign(summand, k);
        result += summand;
        k++;
    } while (absoluteValue(summand) > error);
    return result;
}

public static double absoluteValue(double value) {
    if (value < 0)
        return -value;
    else
        return value;
}

public static double definePreSign(double value, int k) {
    if (k % 2 == 0) {
        return value;
    } else {
        return value * (-1);
    }
}

public static double calcNumeratorPotency(double x, double k) {
    double pot = x;
    for (int i = 0; i < 2 * k; i++) {
        pot *= x;
    }
    return pot;
}

public static double calcDenumeratorFaculty(int k) {
    double fak = 1;
    if (k == 0) {
        return 1;
    } else {
        for (int i = 1; i <= (2 * k + 1); i++) {
            fak *= i;
        }
    }
    return fak;

}

3 个答案:

答案 0 :(得分:3)

您以前似乎曾经使用过另一种语言。 Java的工作与您预期的有所不同。

for (int i = 0; i <= k; k++) {
    fak *= (2 * i + 1);
}

此特定循环肯定无法按预期工作。您增加了k,但是i应该增长了吗?可能是您要写的:

for (int i = 0; i <= k; i++) {
    fak *= (2 * i + 1);
}

因为循环计数为k,而不是i,所以循环继续,直到k超出整数范围并变为Integer.MIN_VALUE。到那时,您的循环终于终止了。 :)

另一个完全不同的注释,它是一种建设性的批评:您可能想看看默认的Java样式指南(https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/styleguide.md

小节录:

// Bad.
//   - This offers poor visual separation of operations.
int foo=a+b+1;

// Good.
int foo = a + b + 1;

标识符和运算符之间的空格非常有用,既可以用数字进行运算,又可以使用很多不同的东西。

答案 1 :(得分:2)

我不太清楚您在berechnePotberechnePot中所计算的内容。从上下文来看,它们似乎是分子和分母。

使用调试器运行代码,我发现summand的计算非常错误,并且递减速度非常慢。这就是为什么要花这么长时间的原因。

Math类提供了一种pow方法,因此您实际上并不需要使用for循环来计算功效。我认为您可能会使这个问题变得过于复杂。我会写一个getSummand方法和一个factorial方法:

private static double getSummand(double x, int k) {
    int power = k * 2 + 1;
    double numerator = Math.pow(x, power);
    double denominator = factorial(power);
    int sign = k % 2 == 1 ? -1 : 1;
    return numerator / denominator * sign;
}

private static double factorial(int x) {
    double result = 1;
    for (int i = 1; i <= x; i++) {
        result *= i;
    }
    return result;
}

并像这样使用它们:

public static double sinus(double x) {
    double error = 0.001;

    double summand = 0;
    double sum = 0;

    int k = 0;
    do {
        summand = getSummand(x, k);
        sum += summand;

        k++;
    } while (Math.abs(summand) > error);
    return sum;
}

如果这是一项分配,并且不允许您使用Math类中的任何东西,则可以编写自己的pow方法,如下所示:

private static double pow(double x, int p) {
    double result = 1;
    for (int i = 0 ; i < p ; i++) {
        result *= x;
    }
    return result;
}

答案 2 :(得分:2)

berechneFak()函数中,else子句中有一个循环。您确实增加了k而不是i,所以i <= k始终为真。尝试在调试器中查看它。这是使速度变慢的循环。

因此,每次k都会以单个增量计算最大整数值2,147,483,647,然后溢出到负值,此时循环将结束。

只需澄清一下:我不是在看数学是否正确,而只是在看程序为什么运行缓慢。