茉莉花新闻网

中華青年思想與行動的聚合地

这个求 sin 的代码,感觉无懈可击啊,为什么会不对呢?

Pandora Eartha的回答

不能把数学上的结论不加考虑地带到计算机来.

先回答你的这个问题, 再举一些常见的计算机数学特性.

这个泰勒展开式是完全正确的, 对一切 x\in \text R 都收敛, 其实对虚数也收敛.

但是为什么带入 x=50 的时候, 计算值和理论值差这么多呢?

v2 5877422caed0b1555c09067b70b1ab12 1440w

你这个函数输出的数据类型是 double , 那我们就来回忆一下 IEEE754标准中, 浮点数是怎么定义的.

浮点数是由数符S, 阶码E(移码表示), 尾数M 构成的.

对于在浮点数表示范围内的实数 D , 有

D=(-1)^S\times M\times R^{E} , 在这里我们规定 R=2 .

类似我们的十进制科学技术法

dec=(-1)^A\times B\times 10^C

例如

\begin{align} dec&=1145141919810\\ &=(-1)^0\times1.14514191981\times10^{12} \end{align}

二进制浮点数类似.

对于双精度(64位)浮点数来说, 其阶码为 11 位, 且其阶码的偏置值是 1023

所以其指数部分最大为 2^{2046-1023}=2^{1023}

最小为 2^{1-1023}=2^{-1022} .

尾数部分是 52 位, 省略最高位, 所以其尾数部分最大为

2-2^{-52}

最小为 .

这个结论告诉我们什么呢? 告诉我们, 浮点数的精度是有限的.

精度是 2^{-52} ?

不对, 精度是 2^{E}\times2^{-52} , 这也意味着, 在浮点数表示范围中,

一个数的绝对值如果越大, 其精度就越低.

一个数的绝对值如果越小, 其精度就越高.

因此, 如果一个数非常非常大, 大到了 2^{1023} 级别, 其精度最高也只能有

\begin{align} &2^{1023}\times(2^{-52})\\=&2^{971}\\ =&1.9958403095347198116563727130368\times10^{292} \end{align}

而如果一个数非常小, 其精度就可以达到

\begin{align} &2^{-1022}\\ =&2.2250738585072013830902327173324\times{10^{-308}} \end{align}

所以, 如果你的 x50 , 甚至是

\begin{align} &50!\\ =&3.0414093201713378043612608166065\times{10^{64}}\\=&30414093201713378043612608166064768844377641568960512000000000000 \end{align}

最后都会因为运算过程中数字太大而丢失精度.

那正确的做法是什么呢?

正确的做法是利用三角函数的周期性将数据都转换为 附近的数据.

比如说 x=50 可以转换为

\begin{align} \sin50=\sin (50-15\pi)=\sin2.8761 \end{align}

进一步转换为

\begin{align} \sin2.8761=\sin(\pi-2.8761)=\sin0.2655 \end{align} .

也就是说, 将所有数据都映射到 \begin{align} [0,\frac{\pi}{2}] \end{align} 上.

OK, 那我们把你的代码改写一下.

先判断 x 是否为负数.

v2 b730ef0a90a6eefb64f3f438e5a82fef 1440w

[0,+\infty] 映射到 [0,2\pi)

v2 fe68ef32552e879742f04fd15af92967 720w

(\pi,2\pi) 数据映射到 (0,\pi) 上.

v2 58d6641045fcd90ae283430035c922bd 720w

\begin{align} (\frac{\pi}{2},\pi] \end{align} 映射到 \begin{align} [0,\frac{\pi}{2}] \end{align}

v2 379ee5500ec03070f5bff27f04d41820 720w
import 泰勒展开

x=50 计算正确.

v2 02a795346abee698500604f088f0c2f4 1440w
v2 3e4e4fad62e7aff7e4c11f58b3f99142 1440w

x=5000 计算正确

v2 709924f390bcc8f7e0f71fdd094eee22 1440w
v2 e0cbf8c357ce9ff00084b9cf0f087c6a 1440w

x=500000 能精确到小数点后 4 位.

v2 4261765434e76b1ecb29e66a5929a153 1440w
v2 04cb36a8382f4a08c2db64cd5ac6f70c 1440w

x=-50000 计算正确

v2 9cd273c1ea7bd40096d647aa3526f834 1440w
v2 e197e8925974e281fd4efa4d96d330f3 1440w

v2 b9a31935775a11d2c2d0fd7587cb67c3 1440w

OK, 那我们见识一下常见的计算机特性.

<img src="https://www.zhihu.com/equation?tex=%5Cbegin%7Balign%7D+%26%5Ctext%7Bint%7D%5C+%5C+A%3D2147483647%5C%5C+%26A%2B1%3D-2147483648%5C%5C%5C%5C+%26%5Ctext%7Bunsigned%7D%5C+%5C+B%3D4294967295%5C%5C+%26B%2B1%3D0%5C%5C%5C%5C+%26%5Ctext%7Bdouble%7D%5C+%5C+C%3D2%5E%7B1023%7D%5Ctimes%282-2%5E%7B52%7D%29%5C%5C+%26C%2B2%5E%7B-%5Cinfty%7D%3D%2B%5Cinfty%5C%5C+%26%28-%5Cinfty+%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E7%BB%9D%E5%AF%B9%E5%80%BC%E8%B6%85%E7%BA%A7%E5%A4%A7%E7%9A%84%E8%B4%9F%E6%95%B0%2C+%E4%B8%8D%E4%BB%A3%E8%A1%A8%E6%95%B0%E5%AD%A6%E4%B8%8A%E7%9A%84%E8%B4%9F%E6%97%A0%E7%A9%B7%29%5C%5C%5C%5C+%26%5Ctext%7Bdouble%7D%5C+%5C+D%3D2%5E%7B-1022%7D%5C%5C+%26D-2%5E%7B-%5Cinfty%7D%3D%2B0%5C%5C+%26%28-%5Cinfty+%E8%A1%A8%E7%A4%BA%E4%B8%80%E4%B8%AA%E7%BB%9D%E5%AF%B9%E5%80%BC%E8%B6%85%E7%BA%A7%E5%A4%A7%E7%9A%84%E8%B4%9F%E6%95%B0%2C+%E4%B8%8D%E4%BB%A3%E8%A1%A8%E6%95%B0%E5%AD%A6%E4%B8%8A%E7%9A%84%E8%B4%9F%E6%97%A0%E7%A9%B7%29%5C%5C%5C%5C+%26%5Ctext%7Bdouble%7D%5C+%5C+E%3D0%5C%5C+%26E%3D%2B0%5C%5C%5C%5C+%26%5Ctext%7Blong+long+unsigned+int%7D%5C+%5C+F%3D18446744073709551615%5C%5C+%26F%2B1%3D0%5C%5C%5C%5C+%26%5Ctext%7Blong+long+unsigned+int%7D%5C+%5C+F%3D1%5Ctext%7BULL%7D%5C%5C+%26F%3C%3C63%3DF%5Ctimes2%5E%7B63%7D%3D9223372036854775808%5C%5C%5C%5C+%26%5Ctext%7Blong+long+unsigned+int%7D%5C+%5C+F%3D1%5Ctext%7BULL%7D%5C%5C+%26F%3C%3C64%3DF%5Ctimes2%5E%7B64%7D%3D1%5C%5C%5C%5C+%26%5Ctext%7Blong+long+unsigned+int%7D%5C+%5C+F%3D1%5Ctext%7BULL%7D%5C%5C+%26F%3C%3C65%3DF%5Ctimes2%5E%7B65%7D%3D2%5C%5C%5C%5C+%26%5Ctext%7Blong+long+unsigned+int%7D%5C+%5C+F%3D1%5Ctext%7BULL%7D%5C%5C+%26F%3C%3C1048575%3DF%5Ctimes2%5E%7B1048575%7D%3D9223372036854775808%5C%5C%5C%5C+%26%5Ctext%7Bint%7D%5C+%5C+G%3D123456789%5C%5C+%26%5Ctext%7Bint%7D%5C+%5C+H%3D123456789%5C%5C+%26GH%3D%28123456789%29%5E2%3D-1757895751%5C%5C%5C%5C+%5Cend%7Balign%7D" alt="\begin{align} &\text{int}\ \ A=2147483647\\ &A+1=-2147483648\\\\ &\text{unsigned}\ \ B=4294967295\\ &B+1=0\\\\ &\text{double}\ \ C=2^{1023}\times(2-2^{52})\\ &C+2^{-\infty}=+\infty\\ &(-\infty 表示一个绝对值超级大的负数, 不代表数学上的负无穷)\\\\ &\text{double}\ \ D=2^{-1022}\\ &D-2^{-\infty}=+0\\ &(-\infty 表示一个绝对值超级大的负数, 不代表数学上的负无穷)\\\\ &\text{double}\ \ E=0\\ &E=+0\\\\ &\text{long long unsigned int}\ \ F=18446744073709551615\\ &F+1=0\\\\ &\text{long long unsigned int}\ \ F=1\text{ULL}\\ &F<<63=F\times2^{63}=9223372036854775808\\\\ &\text{long long unsigned int}\ \ F=1\text{ULL}\\ &F<<64=F\times2^{64}=1\\\\ &\text{long long unsigned int}\ \ F=1\text{ULL}\\ &F<<65=F\times2^{65}=2\\\\ &\text{long long unsigned int}\ \ F=1\text{ULL}\\ &F<


Pandora Eartha:【数据结构】链表的算法和代码实现(C语言)Pandora Eartha:C语言计算100亿质数表


//  www.zhihu.com-question-570208543
//  Created by Pandora on 2022/12/5.

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

#define pi 3.1415926535

double sinTaylor(double x){
    bool negative=false;
    if(x<0){
        negative=true;
        x=-x;
    }
    if(x>2*pi){
        int adjust=x/pi/2;
        x=x-adjust*2*pi;
    }
    if(x>pi){
        x=2*pi-x;
        negative=!negative;
    }
    if(x>pi/2){
        x=pi-x;
    }
    int sign=1;
    unsigned n=0;
    double sum=0;
    double term=x;
    while(fabs(term)>=1e-6){
        sum+=sign*term;
        n++;
        sign=-sign;
        term=term*x*x/(2*n+1)/(2*n);
    }
    if(negative){
        sum=-sum;
    }
    return sum;
}

int main(int argc, const char * argv[]) {
    double x=-50000;
    printf("%lf\n",sinTaylor(x));
}

同类信息

查看全部

茉莉花论坛作为一个开放社区,允许您发表任何符合社区规定的文章和评论。

茉莉花新闻网

        中国茉莉花革命网始创于2011年2月20日,受阿拉伯之春的感召,大家共同组织、发起了中国茉莉花革命。后由数名义工无偿坚持至今,并发展成为广受翻墙网民欢迎的新闻聚合网站并提供论坛服务。

新闻汇总

邮件订阅

输入您的邮件地址:

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram