给定 Integer n 和 Double x。计算:sin x + sin sin x +...+sin sin...sin x。其中n——罪的数目

given Integer n and Double x. Calculate: sin x + sinsin x +...+sinsin...sinx. Where n— number of sin

我写道:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Test1 {

    public static void main(String[] args) {

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

            String sn = reader.readLine();
            String sx = reader.readLine();

            int n = Integer.parseInt(sn);
            double x = Double.parseDouble(sx);

            double sum = 0;

            for (int i = 0; i < n; i++) {
                x = Math.sin(x);
                sum += x;
            }

            System.out.println("Sum is: " + sum);
        } catch (Exception e) {
        }
    }
}

但是讲师说,这个代码错了

很明显你的答案是 sum of n term where the ith term has i 正弦嵌套链。

这是执行此操作的代码。请注意,通过使用正确的变量名称和对解决方案的结构进行推理,一切都变得非常清晰。

class Potato
{
    public static void main(String args[])
    {
        double x = 0.5;
        int n = 2;

        double sum = 0;
        for(int i=1;i<=5;i++)
        {
            double term = x;
            for(int j=1;j<=i;j++)
                term = Math.sin(term);
            sum += term;
        }

        System.out.println(sum);
    }
}

对于我这里的特定值,序列是

sin(0.5) + sin(sin(0.5)) ==> 0.9406950936373837

同样使用此 python 片段手动确认:

>>> sin(0.5) + sin(sin(0.5))
0.9406950936373837

但是,你的代码也是正确的,而且效率更高,避免了重复计算。

要了解为什么这是真的:

你可以把term[i]写成sin(term[i-1])

所需的答案是 sum(term),这正是您计算得出的结果。

如果你想效率高一点,也可以这样做:

public static double sum(double x, int n) {
    assert n >= 1;
    double sum = 0;
    double term = x;
    for (int i = 0; i < n; ++i) {
        term = Math.sin(term);
        sum = sum + term;
    }
    return sum;
}

测试:

public static void test() {
    double x = Math.PI / 2;

    System.out.println(sum(x, 1) + " " + Math.sin(x));
    System.out.println(sum(x, 2) + " " + (Math.sin(x) + Math.sin(Math.sin(x))));
    System.out.println(sum(x, 3) + " " + (Math.sin(x) + Math.sin(Math.sin(x)) + Math.sin(Math.sin(Math.sin(x)))));
}

测试输出(两个版本):

1.0 1.0
1.8414709848078965 1.8414709848078965
2.5870951264734545 2.5870951264734545

递归版本

public static double sum(double x, double n) {
    return sum(x, n, Math.sin(x));
}

public static double sum(double x, double n, double term) {
    if (n == 0) {
        return 0;
    }
    return term + sum(x, n - 1, Math.sin(term));
}

您的代码的内部主体,即实际计算答案的算法部分是正确的。

您可以使用 ghci 的交互式 Haskell 会话来检查该部分(这使得重复函数调用等操作变得更加简单)。

例如使用 Haskell 计算可以简化为:(\x n -> sum . tail . take (n+1) $ iterate sin x) 0.5 2,计算 x = 0.5n = 2 并产生 0.9406950936373837

但您可能需要重新阅读问题。输入应该是度数而不是弧度吗?鉴于重复函数应用的模式,输出可能应该是 x + sin(x) + ...,在这种情况下,用于验证目的的 Haskell 代码将是:

(\x n -> sum . take n $ iterate sin x)x = 0.5n = 2 的相同示例将产生 0.979425538604203

而且你的解决方案有一个问题:如果没有输入怎么办?如果只有一根线怎么办?你假设你总是会得到 2 行,但是......情况可能并非如此。你没有任何错误处理。

另外,也许老师要求你把你的重复正弦之和的算法放在它自己的函数中?