Эффективное среднее из трех значений в C
Мы считываем некоторые сигналы с контактов и устанавливаем еще несколько событий, основанных на этом чтении.
Чтобы быть в безопасности, я хочу попробовать булавки 3 раза, сравнить три значения и использовать наиболее распространенное значение (т. е. образец A равен 1, B равен 3 и C равен 1, я хочу использовать 1, Если A B и C все 2, то используйте 2, но если A равен 1, B равен 2 и C равен 3, я хочу снова захватить три образца).
В настоящее время я использую:
int getCAPValues (void)
{
// Get three samples to check CAP signals are stable:
uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // First set of CAP values
for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // second set
for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // third set
if (x == y) || (x == z)
{
//use the x value
}
else if (y == z)
{
// use the y value
x = y;
}
else
{
x = -1;
}
return x;
}
Но это не кажется мне очень эффективным, есть ли лучший способ чтобы сделать это?
Это на доске развития SAMD21 Xplained Pro В C.
Правка:
Я изменил код в соответствии с ответами, только читая значение "z", если оно будет использоваться, и используя delay_us () вместо фиктивных циклов:
int getCAPValues (void)
{
// Get three samples to check CAP signals are stable:
uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // First set of CAP values
delay_us(1);
//for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // second set
// Using most common value, or error code of -1 if all different
if (!(x == y))
{
delay_us(1);
//for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // third set
if (x == z)
{
// use the x/z value
return x;
}
else if (y == z)
{
// use the y/z value
return y;
}
else
{
return -1;
}
}
return x;
}
2 ответа:
Если
x==y
вы собираетесь использовать значениеx
. Так что в этом случае вы можете уклониться от третьего чтения.Я не знаю, насколько изменчивы ваши значения, но это может эффективно почти удвоить производительность, чтобы избежать этой второй задержки, если спорные значения на самом деле редки.
Действительно, если они не редки, то все обоснование может быть недействительным.
PS: Я также думаю, что вы должны использовать ' usleep ()', а не фиктивные циклы. Это зависит от того, что доступно на вашей платформе.int getCAPValues (void) { // Get three samples to check CAP signals are stable: uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // First set of CAP values for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // second set if(x!=y){ //x & y are different. Get a tie-breaker... for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // third set if (y == z) { // use the y value x = y; } else if(x!=z){ //tie-breaking failed... x=-1; } } return x; }
Если вы можете предположить, что
x
,y
аz
- это либо0
, либо1
. Тогда вы можете просто использоватьx+y+z>1
(если большинство из них1
, то сумма больше, чем1
, и сравнение оценивается в1
, а в противном случае оно оценивается в0
).В противном случае ваше (второе) решение, вероятно, является наиболее эффективным. По крайней мере, если вы не знаете вероятностей исходов. Кроме того, засыпание на одну микросекунду будет самой трудоемкой операцией.
Что вы следует учитывать, однако, что, поскольку считывания, вероятно, энергонезависимы, это может отличаться, если вы действительно делаете третье чтение или нет. Кроме того, вы должны, возможно, рассмотреть, если вам нужно сделать полное перечитывание. Если вы, например, считаете, что если первые три чтения из портов все разные, а четвертое чтение равно второму или третьему, вы можете пойти на это, вы можете использовать это в качестве оптимизации. Например:
x = read_port(); y = read_port(); if( x == y ) return x; for(;;) { z = read_port(); if( z == x || z == y ) return z; x = y; y = z; }