从正弦计算余弦的性能和准确性,反之亦然

Performance and accuracy of calculating cosine from sine or vice versa

考虑一个直角三角形,您知道它的斜边和一条直角线 - 让我们说与您感兴趣的角 alpha 相反的直角三角形。 值 sin(alpha) 可以很容易地计算为

sin(alpha) = a / c,

其中 a 是相反的直角,c 是斜边。我不知道相邻导管 b 的长度。什么是更快 and/or 更准确的计算 cos(alpha) 的方法?

一个人可以使用

   sin²(alpha) + cos²(alpha) = 1
=> cos(alpha) = Sqrt(1 - sin²(alpha)),

你有一个乘法,一个减法和一个平方根运算,或者

alpha = asin(a / c)
=> cos(alpha) = cos(asin(a / c)),

你有一个反正弦运算和一个余弦运算(商 a / c 已经计算出来了)。

我对这两种方法的性能和准确性以及是否有更好的方法感兴趣。

我使用以下 C# 代码在 Core i7-6700 @ 3.40GHz、8 GB RAM、运行 Windows 10 和 Visual Studio 2013 上测试了性能:

  var stopwatch = new Stopwatch();
  var random = new Random();

  var numberOfValues = 1000000;
  var repetitions = 100;
  var quotients = new double[numberOfValues];
  var sineValues = new double[numberOfValues];
  var results = new double[numberOfValues];


  // Preparing values for the measurement.
  for (var i = 0; i < numberOfValues; i++)
  {
    quotients[i] = random.NextDouble() / random.NextDouble();
    sineValues[i] = Math.Sin(quotients[i]);
  }


  // First method: Squaring and taking square root.
  stopwatch.Start();
  for (var j = 0; j < repetitions; j++)
  {
    for (var i = 0; i < numberOfValues; i++)
    {
      results[i] = Math.Sqrt(1 - Math.Pow(sineValues[i], 2));
    }
  }
  stopwatch.Stop();
  Console.WriteLine(stopwatch.Elapsed);


  stopwatch.Reset();


  // Second method: Arcsine and cosine.
  stopwatch.Start();
  for (var j = 0; j < repetitions; j++)
  {
    for (var i = 0; i < numberOfValues; i++)
    {
      results[i] = Math.Cos(Math.Asin(quotients[i]));
    }
  }
  stopwatch.Stop();
  Console.WriteLine(stopwatch.Elapsed);

结果:

04.7030170 sec
10.4038198 sec,

这只是两个差异的因数。但是,如果将 Math.Pow 替换为直接乘法,则值将更改为:

00.4991018 sec
10.3393635 sec,

产生大约 20 的系数!