Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.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# C中Math.Sin()和Math.Cos()的准确性#_C#_Clr_Trigonometry - Fatal编程技术网

C# C中Math.Sin()和Math.Cos()的准确性#

C# C中Math.Sin()和Math.Cos()的准确性#,c#,clr,trigonometry,C#,Clr,Trigonometry,我对CLR中内在触发器函数的不精确性感到非常恼火。众所周知 Math.Sin(Math.PI)=0.00000000000000012246063538223773 而不是0。类似的情况也发生在Math.Cos(Math.PI/2)上 但是当我在做一系列的计算时,在特殊情况下,我会评估 Math.Sin(Math.PI/2+x)-Math.Cos(x) 对于x=0.2,结果是零,但是对于x=0.1,结果不是零(试试看)。另一个问题是,当参数是一个大数字时,不准确度会相应地增大 因此,我想知道

我对CLR中内在触发器函数的不精确性感到非常恼火。众所周知

Math.Sin(Math.PI)=0.00000000000000012246063538223773
而不是0。类似的情况也发生在
Math.Cos(Math.PI/2)

但是当我在做一系列的计算时,在特殊情况下,我会评估

Math.Sin(Math.PI/2+x)-Math.Cos(x)
对于x=0.2,结果是零,但是对于x=0.1,结果不是零(试试看)。另一个问题是,当参数是一个大数字时,不准确度会相应地增大


因此,我想知道是否有人用C#编写了一些更好的trig函数表示,以便与世界共享。CLR是否调用实现CORDIC或类似功能的标准C数学库?链接:

这与三角函数的精度无关,而与CLS型系统有关。根据文档,a的精度为15-16位(这正是您得到的),因此您无法对这种类型更精确。因此,如果您想要更高的精度,您需要创建一个能够存储它的新类型

还要注意,您永远不应该编写这样的代码:

double d = CalcFromSomewhere();
if (d == 0)
{
    DoSomething();
}
你应该改为:

double d = CalcFromSomewhere();
double epsilon = 1e-5; // define the precision you are working with
if (Math.Abs(d) < epsilon)
{
    DoSomething();
}
double d=calcfromsomeone();
双ε=1e-5;//定义正在使用的精度
if(数学绝对值(d)
这是浮点精度的结果。可以得到一定数量的有效数字,任何不能精确表示的都是近似值。例如,pi不是一个有理数,因此不可能得到精确的表示。因为不能得到π的精确值,所以不能得到包括π在内的数字的精确正弦和余弦(大多数情况下也不能得到正弦和余弦的精确值)

最好的中间解释是。如果你不想深入这一点,只要记住浮点数通常是近似值,而浮点数计算就像是在地面上移动一堆沙子:无论你用它们做什么,你都会损失一点沙子,拾起一点灰尘


如果你想要精确的表示,你需要找到一个符号代数系统。

我听到了。我对除法的不准确感到非常恼火。前几天我做了:

Console.WriteLine(1.0 / 3.0);
我得到了0.333,而不是正确的答案0.333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333

也许现在你明白问题所在了Math.Pi不等于Pi任何大于1.0/3.0的值都等于三分之一。它们都与真值相差几百万亿次,因此使用Math.Pi或1.0/3.0执行的任何计算也会相差几百万亿次,包括正弦


如果你不喜欢近似算法是近似的,那么就不要使用近似算法。使用精确的算术。当我需要精确的算术时,我用滑铁卢枫树;也许你应该买一份。你需要使用任意精度的十进制库。(.Net 4.0有一个,但不是小数)

有几种流行的:


我拒绝错误是由于四舍五入造成的想法。可以做的是使用6项泰勒展开式定义sin(x),如下所示:

    const double π=Math.PI;
    const double π2=Math.PI/2;
    const double π4=Math.PI/4;

    public static double Sin(double x)
    {

        if (x==0) { return 0; }
        if (x<0) { return -Sin(-x); }
        if (x>π) { return -Sin(x-π); }
        if (x>π4) { return Cos(π2-x); }

        double x2=x*x;

        return x*(x2/6*(x2/20*(x2/42*(x2/72*(x2/110*(x2/156-1)+1)-1)+1)-1)+1);
    }

    public static double Cos(double x)
    {
        if (x==0) { return 1; }
        if (x<0) { return Cos(-x); }
        if (x>π) { return -Cos(x-π); }
        if (x>π4) { return Sin(π2-x); }

        double x2=x*x;

        return x2/2*(x2/12*(x2/30*(x2/56*(x2/90*(x2/132-1)+1)-1)+1)-1)+1;
    }
constdoubleπ=Math.PI;
常数双π2=Math.PI/2;
常数双π4=Math.PI/4;
公共静态双Sin(双x)
{
如果(x==0){返回0;}
if(xπ){return-Sin(xπ);}
如果(x>π4){返回Cos(π2-x);}
双x2=x*x;
返回x*(x2/6*(x2/20*(x2/42*(x2/72*(x2/110*(x2/156-1)+1)-1)+1);
}
公共静态双Cos(双x)
{
如果(x==0){返回1;}
if(xπ){return-Cos(xπ);}
如果(x>π4){返回Sin(π2-x);}
双x2=x*x;
返回x2/2*(x2/12*(x2/30*(x2/56*(x2/90*(x2/132-1)+1)-1)+1;
}
典型错误为
1e-16
和wors
    public static double Sin(double d) {
        d = d % (2 * Math.PI); // Math.Sin calculates wrong results for values larger than 1e6
        if (d == 0 || d == Math.PI || d == -Math.PI) {
            return 0.0;
        }
        else {
            return Math.Sin(d);
        }
    }

    public static double Cos(double d) {
        d = d % (2 * Math.PI); // Math.Cos calculates wrong results for values larger than 1e6
        double multipleOfPi = d / Math.PI; // avoid calling the expensive modulo function twice
        if (multipleOfPi == 0.5 || multipleOfPi == -0.5 || multipleOfPi == 1.5 || multipleOfPi == -1.5) { 
            return 0.0;
        }
        else {
            return Math.Cos(d);
        }
    }