Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将cos和sin存储到一个向量中并得到奇怪的值_C++_Floating Point - Fatal编程技术网

C++ 将cos和sin存储到一个向量中并得到奇怪的值

C++ 将cos和sin存储到一个向量中并得到奇怪的值,c++,floating-point,C++,Floating Point,我的代码 我期望的产量 double to_radians(double theta) { return (M_PI * theta) / 180.0; } int main() { std::vector<std::pair<double, double>> points; for (double theta = 0.0; theta <= 360.0; theta += 30.0) { points.push_b

我的代码

我期望的产量

double to_radians(double theta)
{
    return (M_PI * theta) / 180.0;
}

int main()
{
    std::vector<std::pair<double, double>> points;
    for (double theta = 0.0; theta <= 360.0; theta += 30.0)
    {
        points.push_back(std::make_pair(std::cos(to_radians(theta)), std::sin(to_radians(theta))));
    }
    for (auto point : points)
        std::cout << point.first << " " << point.second << "\n";
}
我得到的输出:

1 0 0.866025 0.5 0.5 0.866025 0 1 -0.5 0.866025 -0.866025 0.5 -1 0 -0.866025 -0.5 -0.5 -0.866025 0 -1 0.5 -0.866025 0.866025 -0.5 1 0 正如你所看到的,我得到的是这些奇怪的值,而不是零。有人能解释为什么会发生这种情况吗?

6.12303e-17,举个例子,表示值6.12303*10-17,或0.00000000000000000612303

得到这个值的原因是,没有将cos应用于π/2,它不能表示为双精度,反正它是无理的。cos函数应用于一个接近π/2的双精度函数,通过将90乘以M_PI,再除以180得到。因为参数不是π/2,所以结果不必是0。事实上,由于浮点数在接近零时密度更大,因此对于任何浮点格式来说,对任何浮点数应用正确的四舍五入cos都不太可能产生正好为零的结果

事实上,由于π/2中cos的导数为-1,因此表达式cosM_PI/2.0的值是M_PI/2和π/2之间差的近似值。由于双精度IEEE 754格式只能表示任意数字的前16位左右的第一个十进制数字,因此这种差异实际上是d*10-17的数量级

请注意,相同的参数适用于获得0.5作为cosM_PI/3.0的结果,甚至-1.0作为cosM_PI的结果。不同之处在于有许多浮点数,有些非常小,大约为0,它们可以非常精确地表示预期的非零结果。相比之下,0.5和-1.0只有几个邻居,对于足够接近π/3和π的输入,数字0.5和-1.0最终作为最接近的可表示双精度值返回到相应的数学结果,而不是1/2或-1,因为输入不是π/3或π

最简单的解决方案是使用假设函数cosdeg和sindeg直接计算角度的余弦和正弦。由于60和90可精确表示为双精度浮点数,因此这些函数没有理由不返回0.5或0.0也可精确表示为双精度浮点数。我之前问过,但没有人指出任何已经可用的实现

njuffa指出的函数sinpi和cospi通常是可用的,它们允许计算正弦和余弦或π/2、π/4甚至7.5*π,但不能计算π/3,因为它们必须应用的数字1/3不能用二进制浮点精确表示。

6.12303e-17,举个例子,表示值6.12303*10-17,或0.00000000000000000612303

得到这个值的原因是,没有将cos应用于π/2,它不能表示为双精度,反正它是无理的。cos函数应用于一个接近π/2的双精度函数,通过将90乘以M_PI,再除以180得到。因为参数不是π/2,所以结果不必是0。事实上,由于浮点数在接近零时密度更大,因此对于任何浮点格式来说,对任何浮点数应用正确的四舍五入cos都不太可能产生正好为零的结果

事实上,由于π/2中cos的导数为-1,因此表达式cosM_PI/2.0的值是M_PI/2和π/2之间差的近似值。由于双精度IEEE 754格式只能表示任意数字的前16位左右的第一个十进制数字,因此这种差异实际上是d*10-17的数量级

请注意,相同的参数适用于获得0.5作为cosM_PI/3.0的结果,甚至-1.0作为cosM_PI的结果。不同之处在于有许多浮点数,有些非常小,大约为0,它们可以非常精确地表示预期的非零结果。相比之下,0.5和-1.0只有几个邻居,对于足够接近π/3和π的输入,数字0.5和-1.0最终作为最接近的可表示双精度值返回到相应的数学结果,而不是1/2或-1,因为输入不是π/3或π

最简单的解决方案是使用假设函数cosdeg和sindeg直接计算角度的余弦和正弦。由于60和90可精确表示为双精度浮点数,因此这些函数没有理由不返回0.5或0.0也可精确表示为双精度浮点数。我之前问过,但没有人指出任何已经可用的实现


njuffa指出的函数sinpi和cospi经常可用,它们允许计算正弦和余弦或π/2、π/4甚至7.5*π,但不计算π/3,因为它们必须应用的数字1/3不能用二进制浮点精确表示。

这是一个浮点舍入错误。触发函数以数学形式实现
在计算级别上近似的系列,导致数字非常接近零,例如6.12303e-17,而不是预期的0。

这是一个浮点舍入错误。Trig函数是以数学级数的形式实现的,在计算层面上近似,这导致数字非常接近于零,例如6.12303e-17,而不是预期的0。

我认为您的数据是正确的,6.12303e-17基本上是0。它是6到十倍的第十七倍的功率,它是除了提供的答案之外的0.00万,000是10000,这是一个有益的阅读。你可能想检查你的平台是否提供了超出当前C++标准的函数SIMPI和CSPI。如果是这样,您应该通过调用sinpitheta/180.0和cospitheta/180.0来获得更准确的结果。是一个提供这些功能的库。我认为您的数据是正确的,6.12303e-17本质上是0。它是6到十倍的第十七倍的功率,它是除了提供的答案之外的0.00万,000是10000,这是一个有益的阅读。你可能想检查你的平台是否提供了超出当前C++标准的函数SIMPI和CSPI。如果是这样,您应该通过调用sinpitheta/180.0和cospitheta/180.0来获得更准确的结果。是一个提供这些函数的库。正确舍入的双精度cos或sin不会为任何非零参数生成0。实施的细节与此无关,这是绝对正确的。你的答案解释了π/2是一个接近无理数的双精度数,这是一个更好、更简洁的答案。感谢您的评论。正确四舍五入的双精度cos或sin不会为任何非零参数生成0。实施的细节与此无关,这是绝对正确的。你的答案解释了π/2是一个接近无理数的双精度数,这是一个更好、更简洁的答案。谢谢你的评论。 1 0 0.866025 0.5 0.5 0.866025 6.12303e-17 1 -0.5 0.866025 -0.866025 0.5 -1 1.22461e-16 -0.866025 -0.5 -0.5 -0.866025 -1.83691e-16 -1 0.5 -0.866025 0.866025 -0.5 1 -2.44921e-16