在操作期间的微控制器float output_value
将给出不同的值(控制算法)。我想利用某种“查找表”,在其中我比较从float output_value
找到float final_output_value
的每个值。
我现在有很多if语句,例如:
if(output_value > 3.0 && output_value < 5.0)
{
final_output_value = 3.2;
}
if(output_value > 5.0 && output_value < 8.0)
{
final_output_value = 5.7
}
这就是这个想法。我正在寻找一种更有效的方式,有人知道更好的方法吗?
答案 0 :(得分:1)
这里有许多决定因素你不提,所以让我概述一下:
我有一个额外的问题可能会改变我给出的建议(我说这是因为我只测试了一个变体,我不知道另一个的影响)是否可以优化范围检查。
你有这两个:
3.0 < v < 5.0
5.0 < v < 8.0
但5.0 完全 呢?
你可以改写这样的范围:
3.0 <= v < 5.0
5.0 <= v < 8.0
(或将等号放在另一个上),这样范围是连续的,没有空洞?我假设是的,你可以。
无论如何,我所做的是:
基本上,&#34;线性&#34;代码方法看起来像这样:
private double IfStatementLookup(double input)
{
if (input < 01.0) return 01.0;
if (input < 02.0) return 02.0;
if (input < 03.0) return 03.0;
if (input < 04.0) return 04.0;
if (input < 05.0) return 05.0;
依此类推< 300
,基本上是一个简单的&#34;天花板&#34;函数表示一组值。因此0 <= input < 1
会返回1
,依此类推。
表驱动的方法如下所示:
private double TableLookup(double input)
{
if (input >= 300)
return 0;
int lower = 0;
int upper = _Table.Length - 1;
while (lower <= upper)
{
int middle = lower + (upper - lower) / 2;
if (input < _Table[middle][0])
upper = middle - 1;
else
lower = middle + 1;
}
return _Table[upper][1];
}
if语句稍微好一点的版本如下:
double SlightlyOptimizedIfStatementLookup(double input)
{
if (input < 100)
{
if (input < 50)
{
if (input < 01.0) return 01.0;
if (input < 02.0) return 02.0;
if (input < 03.0) return 03.0;
}
// if-statements for 50-100
}
if (input < 200)
// same here for 200-299
if (input < 300)
// same here for 300-399
现在,在我展示基准测试结果之前,这里有一些要点:
< 25
和< 75
添加if语句,可以进一步更改if语句稍微好一点的版本在各个层面内等等可以在此答案的底部找到整个LINQPad程序。请务必在启用优化的情况下运行它(右下方的/o+
小按钮)。
CAVEAT!我可能在程序中犯了许多错误,这些错误有可能使我的整个答案无效。请单独验证结果。
在任何情况下,这里都是缩写的基准测试结果:
Method | Mean | Error | StdDev |
------------------------------ |----------:|----------:|----------:|
TableDriven | 163.95 us | 0.9125 us | 0.7620 us |
LinearIfStatements | 314.41 us | 2.3511 us | 2.0842 us |
SlightlyOptimizedIfStatements | 64.43 us | 0.7900 us | 0.7390 us |
结论:基于代码的基于if语句的方法优于(我的简单)表驱动方法。
这是整个程序,请注意由于if语句的数量有点长。
void Main()
{
new LookupTest().Validate();
BenchmarkRunner.Run<LookupTest>();
}
public class LookupTest
{
public LookupTest()
{
_Inputs = Enumerable.Range(0, 3000).Select(idx => idx / 10.0).ToArray();
_Table = _Inputs.Select(input => new[] { input, IfStatementLookup(input) }).ToArray();
TableDriven();
}
public void Validate()
{
bool anyMismatch = false;
foreach (var input in _Inputs)
{
var ifStatements = IfStatementLookup(input);
var slightlyOptimizedIfStatements = SlightlyOptimizedIfStatementLookup(input);
var tableDriven = TableLookup(input);
if (ifStatements != tableDriven || ifStatements != slightlyOptimizedIfStatements)
{
$"{input:0.00} => if: {ifStatements}, lookup: {tableDriven}, if+: {slightlyOptimizedIfStatements}".Dump();
anyMismatch = true;
}
}
if (anyMismatch)
throw new InvalidOperationException();
}
private double[] _Inputs;
private double[][] _Table;
[Benchmark]
public void TableDriven()
{
double sum = 0;
for (int index = 0; index < _Inputs.Length; index++)
{
sum += TableLookup(_Inputs[index]);
}
if (sum < 0)
throw new InvalidOperationException();
}
private double TableLookup(double input)
{
if (input >= 300)
return 0;
int lower = 0;
int upper = _Table.Length - 1;
while (lower <= upper)
{
int middle = lower + (upper - lower) / 2;
if (input < _Table[middle][0])
upper = middle - 1;
else
lower = middle + 1;
}
return _Table[upper][1];
}
[Benchmark]
public void LinearIfStatements()
{
double sum = 0;
for (int index = 0; index < _Inputs.Length; index++)
{
sum += IfStatementLookup(_Inputs[index]);
}
if (sum < 0)
throw new InvalidOperationException();
}
[Benchmark]
public void SlightlyOptimizedIfStatements()
{
double sum = 0;
for (int index = 0; index < _Inputs.Length; index++)
{
sum += SlightlyOptimizedIfStatementLookup(_Inputs[index]);
}
if (sum < 0)
throw new InvalidOperationException();
}
private double IfStatementLookup(double input)
{
if (input < 01.0) return 01.0;
if (input < 02.0) return 02.0;
if (input < 03.0) return 03.0;
if (input < 04.0) return 04.0;
if (input < 05.0) return 05.0;
if (input < 06.0) return 06.0;
if (input < 07.0) return 07.0;
if (input < 08.0) return 08.0;
if (input < 09.0) return 09.0;
if (input < 10.0) return 10.0;
if (input < 11.0) return 11.0;
if (input < 12.0) return 12.0;
if (input < 13.0) return 13.0;
if (input < 14.0) return 14.0;
if (input < 15.0) return 15.0;
if (input < 16.0) return 16.0;
if (input < 17.0) return 17.0;
if (input < 18.0) return 18.0;
if (input < 19.0) return 19.0;
if (input < 20.0) return 20.0;
if (input < 21.0) return 21.0;
if (input < 22.0) return 22.0;
if (input < 23.0) return 23.0;
if (input < 24.0) return 24.0;
if (input < 25.0) return 25.0;
if (input < 26.0) return 26.0;
if (input < 27.0) return 27.0;
if (input < 28.0) return 28.0;
if (input < 29.0) return 29.0;
if (input < 30.0) return 30.0;
if (input < 31.0) return 31.0;
if (input < 32.0) return 32.0;
if (input < 33.0) return 33.0;
if (input < 34.0) return 34.0;
if (input < 35.0) return 35.0;
if (input < 36.0) return 36.0;
if (input < 37.0) return 37.0;
if (input < 38.0) return 38.0;
if (input < 39.0) return 39.0;
if (input < 40.0) return 40.0;
if (input < 41.0) return 41.0;
if (input < 42.0) return 42.0;
if (input < 43.0) return 43.0;
if (input < 44.0) return 44.0;
if (input < 45.0) return 45.0;
if (input < 46.0) return 46.0;
if (input < 47.0) return 47.0;
if (input < 48.0) return 48.0;
if (input < 49.0) return 49.0;
if (input < 50.0) return 50.0;
if (input < 51.0) return 51.0;
if (input < 52.0) return 52.0;
if (input < 53.0) return 53.0;
if (input < 54.0) return 54.0;
if (input < 55.0) return 55.0;
if (input < 56.0) return 56.0;
if (input < 57.0) return 57.0;
if (input < 58.0) return 58.0;
if (input < 59.0) return 59.0;
if (input < 60.0) return 60.0;
if (input < 61.0) return 61.0;
if (input < 62.0) return 62.0;
if (input < 63.0) return 63.0;
if (input < 64.0) return 64.0;
if (input < 65.0) return 65.0;
if (input < 66.0) return 66.0;
if (input < 67.0) return 67.0;
if (input < 68.0) return 68.0;
if (input < 69.0) return 69.0;
if (input < 70.0) return 70.0;
if (input < 71.0) return 71.0;
if (input < 72.0) return 72.0;
if (input < 73.0) return 73.0;
if (input < 74.0) return 74.0;
if (input < 75.0) return 75.0;
if (input < 76.0) return 76.0;
if (input < 77.0) return 77.0;
if (input < 78.0) return 78.0;
if (input < 79.0) return 79.0;
if (input < 80.0) return 80.0;
if (input < 81.0) return 81.0;
if (input < 82.0) return 82.0;
if (input < 83.0) return 83.0;
if (input < 84.0) return 84.0;
if (input < 85.0) return 85.0;
if (input < 86.0) return 86.0;
if (input < 87.0) return 87.0;
if (input < 88.0) return 88.0;
if (input < 89.0) return 89.0;
if (input < 90.0) return 90.0;
if (input < 91.0) return 91.0;
if (input < 92.0) return 92.0;
if (input < 93.0) return 93.0;
if (input < 94.0) return 94.0;
if (input < 95.0) return 95.0;
if (input < 96.0) return 96.0;
if (input < 97.0) return 97.0;
if (input < 98.0) return 98.0;
if (input < 99.0) return 99.0;
if (input < 100.0) return 100.0;
if (input < 101.0) return 101.0;
if (input < 102.0) return 102.0;
if (input < 103.0) return 103.0;
if (input < 104.0) return 104.0;
if (input < 105.0) return 105.0;
if (input < 106.0) return 106.0;
if (input < 107.0) return 107.0;
if (input < 108.0) return 108.0;
if (input < 109.0) return 109.0;
if (input < 110.0) return 110.0;
if (input < 111.0) return 111.0;
if (input < 112.0) return 112.0;
if (input < 113.0) return 113.0;
if (input < 114.0) return 114.0;
if (input < 115.0) return 115.0;
if (input < 116.0) return 116.0;
if (input < 117.0) return 117.0;
if (input < 118.0) return 118.0;
if (input < 119.0) return 119.0;
if (input < 120.0) return 120.0;
if (input < 121.0) return 121.0;
if (input < 122.0) return 122.0;
if (input < 123.0) return 123.0;
if (input < 124.0) return 124.0;
if (input < 125.0) return 125.0;
if (input < 126.0) return 126.0;
if (input < 127.0) return 127.0;
if (input < 128.0) return 128.0;
if (input < 129.0) return 129.0;
if (input < 130.0) return 130.0;
if (input < 131.0) return 131.0;
if (input < 132.0) return 132.0;
if (input < 133.0) return 133.0;
if (input < 134.0) return 134.0;
if (input < 135.0) return 135.0;
if (input < 136.0) return 136.0;
if (input < 137.0) return 137.0;
if (input < 138.0) return 138.0;
if (input < 139.0) return 139.0;
if (input < 140.0) return 140.0;
if (input < 141.0) return 141.0;
if (input < 142.0) return 142.0;
if (input < 143.0) return 143.0;
if (input < 144.0) return 144.0;
if (input < 145.0) return 145.0;
if (input < 146.0) return 146.0;
if (input < 147.0) return 147.0;
if (input < 148.0) return 148.0;
if (input < 149.0) return 149.0;
if (input < 150.0) return 150.0;
if (input < 151.0) return 151.0;
if (input < 152.0) return 152.0;
if (input < 153.0) return 153.0;
if (input < 154.0) return 154.0;
if (input < 155.0) return 155.0;
if (input < 156.0) return 156.0;
if (input < 157.0) return 157.0;
if (input < 158.0) return 158.0;
if (input < 159.0) return 159.0;
if (input < 160.0) return 160.0;
if (input < 161.0) return 161.0;
if (input < 162.0) return 162.0;
if (input < 163.0) return 163.0;
if (input < 164.0) return 164.0;
if (input < 165.0) return 165.0;
if (input < 166.0) return 166.0;
if (input < 167.0) return 167.0;
if (input < 168.0) return 168.0;
if (input < 169.0) return 169.0;
if (input < 170.0) return 170.0;
if (input < 171.0) return 171.0;
if (input < 172.0) return 172.0;
if (input < 173.0) return 173.0;
if (input < 174.0) return 174.0;
if (input < 175.0) return 175.0;
if (input < 176.0) return 176.0;
if (input < 177.0) return 177.0;
if (input < 178.0) return 178.0;
if (input < 179.0) return 179.0;
if (input < 180.0) return 180.0;
if (input < 181.0) return 181.0;
if (input < 182.0) return 182.0;
if (input < 183.0) return 183.0;
if (input < 184.0) return 184.0;
if (input < 185.0) return 185.0;
if (input < 186.0) return 186.0;
if (input < 187.0) return 187.0;
if (input < 188.0) return 188.0;
if (input < 189.0) return 189.0;
if (input < 190.0) return 190.0;
if (input < 191.0) return 191.0;
if (input < 192.0) return 192.0;
if (input < 193.0) return 193.0;
if (input < 194.0) return 194.0;
if (input < 195.0) return 195.0;
if (input < 196.0) return 196.0;
if (input < 197.0) return 197.0;
if (input < 198.0) return 198.0;
if (input < 199.0) return 199.0;
# error Stack Overflow limited my answer
// Copy the 200-299-block above and just
// Alt+Shift Selection to mark the 2's and change them to 3's
// BOTH PLACES
return 0;
}
double SlightlyOptimizedIfStatementLookup(double input)
{
if (input < 100)
{
if (input < 50)
{
if (input < 01.0) return 01.0;
if (input < 02.0) return 02.0;
if (input < 03.0) return 03.0;
if (input < 04.0) return 04.0;
if (input < 05.0) return 05.0;
if (input < 06.0) return 06.0;
if (input < 07.0) return 07.0;
if (input < 08.0) return 08.0;
if (input < 09.0) return 09.0;
if (input < 10.0) return 10.0;
if (input < 11.0) return 11.0;
if (input < 12.0) return 12.0;
if (input < 13.0) return 13.0;
if (input < 14.0) return 14.0;
if (input < 15.0) return 15.0;
if (input < 16.0) return 16.0;
if (input < 17.0) return 17.0;
if (input < 18.0) return 18.0;
if (input < 19.0) return 19.0;
if (input < 20.0) return 20.0;
if (input < 21.0) return 21.0;
if (input < 22.0) return 22.0;
if (input < 23.0) return 23.0;
if (input < 24.0) return 24.0;
if (input < 25.0) return 25.0;
if (input < 26.0) return 26.0;
if (input < 27.0) return 27.0;
if (input < 28.0) return 28.0;
if (input < 29.0) return 29.0;
if (input < 30.0) return 30.0;
if (input < 31.0) return 31.0;
if (input < 32.0) return 32.0;
if (input < 33.0) return 33.0;
if (input < 34.0) return 34.0;
if (input < 35.0) return 35.0;
if (input < 36.0) return 36.0;
if (input < 37.0) return 37.0;
if (input < 38.0) return 38.0;
if (input < 39.0) return 39.0;
if (input < 40.0) return 40.0;
if (input < 41.0) return 41.0;
if (input < 42.0) return 42.0;
if (input < 43.0) return 43.0;
if (input < 44.0) return 44.0;
if (input < 45.0) return 45.0;
if (input < 46.0) return 46.0;
if (input < 47.0) return 47.0;
if (input < 48.0) return 48.0;
if (input < 49.0) return 49.0;
return 50.0;
}
if (input < 51.0) return 51.0;
if (input < 52.0) return 52.0;
if (input < 53.0) return 53.0;
if (input < 54.0) return 54.0;
if (input < 55.0) return 55.0;
if (input < 56.0) return 56.0;
if (input < 57.0) return 57.0;
if (input < 58.0) return 58.0;
if (input < 59.0) return 59.0;
if (input < 60.0) return 60.0;
if (input < 61.0) return 61.0;
if (input < 62.0) return 62.0;
if (input < 63.0) return 63.0;
if (input < 64.0) return 64.0;
if (input < 65.0) return 65.0;
if (input < 66.0) return 66.0;
if (input < 67.0) return 67.0;
if (input < 68.0) return 68.0;
if (input < 69.0) return 69.0;
if (input < 70.0) return 70.0;
if (input < 71.0) return 71.0;
if (input < 72.0) return 72.0;
if (input < 73.0) return 73.0;
if (input < 74.0) return 74.0;
if (input < 75.0) return 75.0;
if (input < 76.0) return 76.0;
if (input < 77.0) return 77.0;
if (input < 78.0) return 78.0;
if (input < 79.0) return 79.0;
if (input < 80.0) return 80.0;
if (input < 81.0) return 81.0;
if (input < 82.0) return 82.0;
if (input < 83.0) return 83.0;
if (input < 84.0) return 84.0;
if (input < 85.0) return 85.0;
if (input < 86.0) return 86.0;
if (input < 87.0) return 87.0;
if (input < 88.0) return 88.0;
if (input < 89.0) return 89.0;
if (input < 90.0) return 90.0;
if (input < 91.0) return 91.0;
if (input < 92.0) return 92.0;
if (input < 93.0) return 93.0;
if (input < 94.0) return 94.0;
if (input < 95.0) return 95.0;
if (input < 96.0) return 96.0;
if (input < 97.0) return 97.0;
if (input < 98.0) return 98.0;
if (input < 99.0) return 99.0;
return 100.0;
}
if (input < 200)
{
if (input < 150)
{
if (input < 101.0) return 101.0;
if (input < 102.0) return 102.0;
if (input < 103.0) return 103.0;
if (input < 104.0) return 104.0;
if (input < 105.0) return 105.0;
if (input < 106.0) return 106.0;
if (input < 107.0) return 107.0;
if (input < 108.0) return 108.0;
if (input < 109.0) return 109.0;
if (input < 110.0) return 110.0;
if (input < 111.0) return 111.0;
if (input < 112.0) return 112.0;
if (input < 113.0) return 113.0;
if (input < 114.0) return 114.0;
if (input < 115.0) return 115.0;
if (input < 116.0) return 116.0;
if (input < 117.0) return 117.0;
if (input < 118.0) return 118.0;
if (input < 119.0) return 119.0;
if (input < 120.0) return 120.0;
if (input < 121.0) return 121.0;
if (input < 122.0) return 122.0;
if (input < 123.0) return 123.0;
if (input < 124.0) return 124.0;
if (input < 125.0) return 125.0;
if (input < 126.0) return 126.0;
if (input < 127.0) return 127.0;
if (input < 128.0) return 128.0;
if (input < 129.0) return 129.0;
if (input < 130.0) return 130.0;
if (input < 131.0) return 131.0;
if (input < 132.0) return 132.0;
if (input < 133.0) return 133.0;
if (input < 134.0) return 134.0;
if (input < 135.0) return 135.0;
if (input < 136.0) return 136.0;
if (input < 137.0) return 137.0;
if (input < 138.0) return 138.0;
if (input < 139.0) return 139.0;
if (input < 140.0) return 140.0;
if (input < 141.0) return 141.0;
if (input < 142.0) return 142.0;
if (input < 143.0) return 143.0;
if (input < 144.0) return 144.0;
if (input < 145.0) return 145.0;
if (input < 146.0) return 146.0;
if (input < 147.0) return 147.0;
if (input < 148.0) return 148.0;
if (input < 149.0) return 149.0;
return 150.0;
}
if (input < 151.0) return 151.0;
if (input < 152.0) return 152.0;
if (input < 153.0) return 153.0;
if (input < 154.0) return 154.0;
if (input < 155.0) return 155.0;
if (input < 156.0) return 156.0;
if (input < 157.0) return 157.0;
if (input < 158.0) return 158.0;
if (input < 159.0) return 159.0;
if (input < 160.0) return 160.0;
if (input < 161.0) return 161.0;
if (input < 162.0) return 162.0;
if (input < 163.0) return 163.0;
if (input < 164.0) return 164.0;
if (input < 165.0) return 165.0;
if (input < 166.0) return 166.0;
if (input < 167.0) return 167.0;
if (input < 168.0) return 168.0;
if (input < 169.0) return 169.0;
if (input < 170.0) return 170.0;
if (input < 171.0) return 171.0;
if (input < 172.0) return 172.0;
if (input < 173.0) return 173.0;
if (input < 174.0) return 174.0;
if (input < 175.0) return 175.0;
if (input < 176.0) return 176.0;
if (input < 177.0) return 177.0;
if (input < 178.0) return 178.0;
if (input < 179.0) return 179.0;
if (input < 180.0) return 180.0;
if (input < 181.0) return 181.0;
if (input < 182.0) return 182.0;
if (input < 183.0) return 183.0;
if (input < 184.0) return 184.0;
if (input < 185.0) return 185.0;
if (input < 186.0) return 186.0;
if (input < 187.0) return 187.0;
if (input < 188.0) return 188.0;
if (input < 189.0) return 189.0;
if (input < 190.0) return 190.0;
if (input < 191.0) return 191.0;
if (input < 192.0) return 192.0;
if (input < 193.0) return 193.0;
if (input < 194.0) return 194.0;
if (input < 195.0) return 195.0;
if (input < 196.0) return 196.0;
if (input < 197.0) return 197.0;
if (input < 198.0) return 198.0;
if (input < 199.0) return 199.0;
return 200.0;
}
if (input < 300)
{
# error Stack Overflow limited my answer
// Copy the 200-block above and just
// Alt+Shift Selection to mark the 2's and change them to 3's
// BOTH PLACES
}
return 0;
}
}
由于Stack Overflow限制为30.000个字符,我不得不缩短上面的程序。您可以下载完整的LINQPad脚本here。