为什么三角函数会给出看似不正确的结果?

17
在我的编程语言中尝试使用三角函数时,我得到了一个看似完全错误的结果。
例如,
sin(90) = 0.8939966636005579

但是我希望sin(90)的结果是1。
发生了什么事情,我该怎么解决?

1
这个回答解决了你的问题吗?Math.Sin()返回了错误的值 - undefined
9
@trincot 这是一个通用的问答对,不受语言限制。请参阅元数据上的问题 - undefined
2
我在元社区看到了这个问题;我不同意需要一个新的问答平台。 - undefined
2
这是一个与编程语言无关的问题,适用于几乎所有的编程语言。无论是哪种编程语言,答案归结为两种(使用库函数进行转换或自己编写转换代码)。 - undefined
7
@trincot “我注意到你说这个话题不是与语言无关的” - 我真的无法理解这里的推理。有人写了一个特定语言的问答对并不能否认这个话题是与语言无关的事实。而且,微小的语法细节、库符号名称的差异等(足以使在Java中显示的代码在S中无效)并不能使话题变得与语言有关 - 因为任何编程语言的用户都可以学习什么是弧度和π。 - undefined
显示剩余2条评论
2个回答

32
为什么会发生这种情况?
三角函数通常要求单位为弧度,而90度是以度为单位的。
这也适用于其他函数,如余弦和正切,不仅仅是正弦函数。
大多数编程语言要求三角函数以弧度为参数。这简化了很多事情,特别是在实现方面,因为代码可能与C语言进行接口交互,而C语言标准化要求三角函数的参数以弧度为单位。
弧度在数学中非常常见,因为它们是角度测量的自然单位。有关更多详细信息,请参阅Math.SE上的这个问题和答案。
一些编程语言可能在其标准库中提供了转换的功能。例如,在Python中,可以通过math.radians函数来实现。三角函数本身通常也会说明它们期望输入的格式。
>>> import math
>>> math.sin(math.radians(90))
1.0

这是一些编程语言标准库中的情况,比如RustJavaPythonMATLAB等等。
然而,许多编程语言并没有提供将角度转换为弧度或反向转换的功能,但实现起来很容易。您可以通过创建一个函数来实现,就像这样 :)
PI = 3.1415926535897932; // or your programming language's standard library's pi constant

function toRadians(degrees) {
  return degrees * (PI / 180);
}

在将角度转换为弧度后,您可以调用三角函数并获得您期望的答案。
有哪些示例可以使用呢?
在编写自己的函数之前,查阅编程语言的标准库和文档是很有帮助的,看看是否存在用于转换的函数。
包含标准库函数的语言有:
Python(三角函数文档 | 转换函数文档,还可以参考如何使用Python将弧度转换为角度)
>>> import math
>>> math.sin(math.radians(90))
1.0

(三角函数文档* | 转换函数文档)

System.out.println(Math.sin(Math.toRadians(90.0)));

(三角函数文档 | 转换函数文档)

sin(deg2rad(90))

不包含标准库函数的语言

(三角函数文档)

#include <stdio.h>
#include <math.h>

double deg2rad(double degrees) {
    return (M_PI / 180) * degrees;
}

int main() {
    printf("%f", sin(deg2rad(90.0)));
}

(注意:并非所有的实现都定义了M_PI,尽管很多实现都包括glibc,它声称来自Unix98和4.4BSD。如果你的实现没有定义,你需要自己定义。)
三角函数文档))
#include <cmath>
#include <iostream>
#include <numbers>

float deg2rad(float degrees)
{
    return (std::numbers::pi_v<float> / 180) * degrees;
}

int main()
{
    std::cout << std::sin(deg2rad(90.0)) << '\n';
}

(三角函数文档*,还请参阅文档中的备注部分,了解SinCosTan的详细信息)

using Math;

public static double DegreesToRadians(double degrees)
{
    return (Math.PI / 180) * degrees;
}

public static int Main() {
    Console.WriteLine(Math.Sin(DegreesToRadians(90.0).ToString());
    return 0;
}

(MDN上的三角函数文档*,特别是度与弧度之间的转换部分,另请参阅如何使sin、cos和tan使用度而不是弧度?)

function degToRad(degrees) {
  return degrees * (Math.PI / 180);
}

console.log(Math.sin(degToRad(90)));

* 这种编程语言在其文档中没有将三角函数分组在一起。请寻找名为sincostan或类似的函数。

2
至少对于C来说,由于标准的sin函数使用的是double而不是float,所以你的deg2rad函数也应该使用double。你还可以根据三角函数的类比引入deg2radf(使用float)和deg2radl(使用long double)。 - undefined
已经修正了错误,谢谢 :) - undefined
2
3.1415926535这个数字的小数位数有不必要的舍入误差。 下一位数字是8,所以你应该向上舍入而不是截断。 或者使用更多的数字,因为这仍然比64位的“double”精度要低。 在3.1415926535897932处截断与使用更多的数字得到相同的“double”值。(我使用了GDB的“print”命令,如print (double)3.14... - undefined
1
修复了。我决定只是对常数增加更多的精确度。 - undefined

0
你得到的结果非常准确。准确性毫无疑问。问题仅仅在于在函数期望弧度时使用了度数。以sin(90)为例,可以通过以下方式将90转换为度数:
90/2π = 14.3239
现在从90中减去14*2π的值,以确定将你放置在90弧度处的正弦波,
90-14*2π = 2.0354 弧度。 将其转换为度数
2.0354*180/π = 116.62 度。 最后, 使用你的计算器计算sin(116.62) = 0.894,这就是你得到的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接