简体   繁体   English

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

[英]Performance and accuracy of calculating cosine from sine or vice versa

Consider a right triangle of which you know the hypotenuse and one of the catheti - let's say the one opposite to the angle alpha in which you are interested. 考虑一个您知道斜边和一个导管的直角三角形-假设与您感兴趣的α角相反的那个三角形。 The value sin(alpha) can be easily calculated as sin(alpha)可以很容易地计算为

sin(alpha) = a / c,

with a being the opposite cathetus and c the hypotenuse. 其中a是相反的导管,c是斜边。 I do not know the length of the adjacent cathetus b. 我不知道相邻的导管的长度b。 What would be the faster and/or more accurate way to calculate cos(alpha) ? 计算cos(alpha)的更快和/或更准确的方法是什么?

One can either use 一个可以使用

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

where you have one multiplication, one subtraction and one square root operation, or 如果您有一个乘法,一个减法和一个平方根运算,或者

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

where you have one inverse sine operation and the cosine operation (the quotient a / c has already been calculated). 其中有一个反正弦运算和余弦运算(已经计算出商a / c )。

I'm interested in the performance and the accuracy of both methods, and if there might be better methods. 我对两种方法的性能和准确性以及是否有更好的方法感兴趣。

I tested the performance with the following code in C#, on a Core i7-6700 @ 3.40GHz, 8 GB RAM, running Windows 10 and Visual Studio 2013: 我在运行Windows 10和Visual Studio 2013的Core i7-6700 @ 3.40GHz,8 GB RAM上使用以下代码在C#中测试了性能:

  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);

Results: 结果:

04.7030170 sec
10.4038198 sec,

which is only a factor of two difference. 这只是两个不同的因素。 However, if Math.Pow is replaced with direct multiplication, the values change to: 但是,如果将Math.Pow替换为直接乘法,则值将更改为:

00.4991018 sec
10.3393635 sec,

which yields a factor of about 20! 产生的系数约为20!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM