从正弦计算余弦的性能和准确性,反之亦然
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 的系数!
考虑一个直角三角形,您知道它的斜边和一条直角线 - 让我们说与您感兴趣的角 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 的系数!