繁体   English   中英

Sin和ToRadians的Java奇怪行为

[英]Java Strange Behavior with Sin and ToRadians

我已经被赋予了使用java来生成Sin表的任务,但是对于某些输入值,我似乎得到了一些非常奇怪的结果。 我使用下面的

System.out.println("| sin(" + currentPoint + ") = " + Math.sin(Math.toRadians(currentPoint)));

Where(int)currentPoint是一个以为单位的值(例如90)

这些结果我觉得很奇怪

| sin(360) = -2.4492935982947064E-16
| sin(180) = 1.2246467991473532E-16
| sin(150) = 0.49999999999999994
| sin(120) = 0.8660254037844387

期待

sin(360) = 0
sin(180) = 0
sin(150) = 0.5
sin(120) = 0.866025404

我错过了什么吗?

您正在处理浮点数,寻找确切的答案对所有值都不起作用。 看看每个计算机科学家应该知道的关于浮点算术的内容 您希望您的测试与某些增量中的预期相当。 请注意,您得到的答案非常接近。 它以咬你的比特来表达价值。

从链接:

将无限多个实数压缩成有限数量的比特需要近似表示。 尽管存在无限多个整数,但在大多数程序中,整数计算的结果可以以32位存储。 相反,给定任何固定数量的位,大多数具有实数的计算将产生无法使用那么多位精确表示的量。 因此,浮点计算的结果通常必须舍入,以便适应其有限表示。 该舍入误差是浮点计算的特征。

如上所述,它不是错误,只是计算机浮点运算的近似。

为了获得预期的答案,因为sin()和cos()在-1,0,+ 1之间,尝试将1轮加到需要的精度并减去1。

x = round15(Math.sin(toRad(angle))+1)-1;

其中round15定义

public double round15(double x){
    DecimalFormat twoDForm = new DecimalFormat("0.##############E0");
    String str = twoDForm.format(x);
    return Double.valueOf(str);
}

它适合我,希望未来的读者喜欢它。

如果您的代码是System.out.println("| sin(" + currentPoint + ") = " + Math.sin(currentPoint)); 你会期待这个:

sin(360) = 0.958915723 
sin(180) = -0.801152636 
sin(150) = -0.71487643 
sin(120) = 0.580611184

换句话说,360弧度的正弦为0.9589,但360度的正弦 0。

编辑:
您看到意外结果的原因仅仅是由于计算精度不高。 如果您只是格式化结果,以便它们具有更少的小数位,则舍入将处理它。 做这样的事情:

System.out.printf("| sin(%d) = %.7f\\n", currentPoint, Math.sin(Math.toRadians(currentPoint)));

然后你会得到更接近你期望的结果。

你的结果是正确的...近似试试这个......

    result=Math.sin(Math.toRadians(value));
    result=format(result);


    private double format(double value) {
            return (double)Math.round(value * 1000000) / 1000000; //you can change this to round up the value(for two position use 100...)
        }

上面的海报是对的。 您期望的正确值是:

Sin(360度)= 0 Sin(180度)= 0 Sin(150度)= .5 Sin(120度)= .866

代码返回正确的答案。 他们只需要四舍五入。 试试这个:

System.out.printf("%s%.3f","| sin(" + currentPoint + ") = ", (Math.sin(Math.toRadians(currentPoint))));

如果要提高或降低小数精度,可以将.3f值更改为不同的数字。

由于某种原因,它显示360的罪为-0.00。 我确信有一个更优雅的解决方案,但这应该工作。

编辑:秒数击败。 使用我上面的代码,它更容易阅读。

另请注意,Math.PI是一个双精度值,不是PI,而只是PI的近似值,Math.sin(Math.PI)为您提供了与sin的实际数学值最接近的double值(Math .PI)。

您必须将角度转换为像这样的弧度

Math.sin(Math.toRadians(90)),结果必须为1

以下是Math.sin方法的API描述。 注意星号中的部分。 我敢打赌,你的预期结果和你得到的结果之间的差异是浮点数计算或舍入问题的缺陷。

public static double sin(double a)

 Returns the trigonometric sine of an angle. Special cases: * If the argument is NaN or an infinity, then the result is NaN. * If the argument is zero, then the result is a zero with the 

与参数相同的符号。

 A result must be within 1 **ulp** of the correctly rounded result. Results 

必须是半单调的。

 Parameters: a - an angle, in radians. Returns: the sine of the argument. 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM