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

时间:2016-05-10 15:24:57

标签: c# performance math floating-accuracy

考虑一个你知道斜边的直角三角形,其中一个导管说的是与你感兴趣的角度α相反的一个。 值var cloudwatchevents = new AWS.CloudWatchEvents(); cloudwatchevents.putRule({ Name: 'my-rule', ScheduleExpression: 'rate(1 hour)` }, function(err, result) { cloudwatchevents.putTargets({ Rule: result.RuleArn, Targets: [ { Arn: myLambdaArn, Id: '1' } ] }, function(err, result) { ... }); }); 可以轻松计算为

sin(alpha)

sin(alpha) = a / c, 是相反的cathetus而c是斜边。我不知道相邻的cathetus b的长度。什么是更快和/或更准确的方法来计算a

可以使用

cos(alpha)

你有一个乘法,一个减法和一个平方根操作,或

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

你有一个反正弦运算和余弦运算(已经计算了商alpha = asin(a / c) => cos(alpha) = cos(asin(a / c)), )。

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

1 个答案:

答案 0 :(得分:2)

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

model = Sequential()
model.add(InputLayer((1, IMG_H, IMG_W)))

model.add(Convolution2D(32, 3, 3, activation = 'relu'))
model.add(Convolution2D(32, 3, 3, activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))

model.add(Dropout(0.3))

model.add(Convolution2D(64, 3, 3, activation = 'relu'))
model.add(Convolution2D(64, 3, 3, activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))

model.add(Dropout(0.3))

model.add(Flatten())
model.add(Dense(256, activation = 'sigmoid'))
model.add(Dropout(0.3))
model.add(Dense(64, activation = 'sigmoid'))
model.add(Dropout(0.3))
model.add(Dense(categories, activation = 'softmax'))

结果:

  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

产生约20倍的因子!