Как проверить, является ли значение в пределах диапазона кратным значению из другого диапазона?

Допустим, у меня есть система, которая распределяет 8820 значений по 96 значениям, округляя их с помощью Banker’s Round (назовите их pulse). Формула:

pulse = BankerRound(8820 * i/96), with i[0,96[

Таким образом, это список импульсов:

0
92
184
276
368
459
551
643
735
827
919
1011
1102
1194
1286
1378
1470
1562
1654
1746
1838
1929
2021
2113
2205
2297
2389
2481
2572
2664
2756
2848
2940
3032
3124
3216
3308
3399
3491
3583
3675
3767
3859
3951
4042
4134
4226
4318
4410
4502
4594
4686
4778
4869
4961
5053
5145
5237
5329
5421
5512
5604
5696
5788
5880
5972
6064
6156
6248
6339
6431
6523
6615
6707
6799
6891
6982
7074
7166
7258
7350
7442
7534
7626
7718
7809
7901
7993
8085
8177
8269
8361
8452
8544
8636
8728

Теперь предположим, что система не посылает мне эти импульсы напрямую. Вместо этого он посылает эти импульсы в 8820-й (назовите их tick):

tick = value * 1/8820

Список тиков, которые я получаю:

0
0.010430839
0.020861678
0.031292517
0.041723356
0.052040816
0.062471655
0.072902494
0.083333333
0.093764172
0.104195011
0.11462585
0.124943311
0.13537415
0.145804989
0.156235828
0.166666667
0.177097506
0.187528345
0.197959184
0.208390023
0.218707483
0.229138322
0.239569161
0.25
0.260430839
0.270861678
0.281292517
0.291609977
0.302040816
0.312471655
0.322902494
0.333333333
0.343764172
0.354195011
0.36462585
0.375056689
0.38537415
0.395804989
0.406235828
0.416666667
0.427097506
0.437528345
0.447959184
0.458276644
0.468707483
0.479138322
0.489569161
0.5
0.510430839
0.520861678
0.531292517
0.541723356
0.552040816
0.562471655
0.572902494
0.583333333
0.593764172
0.604195011
0.61462585
0.624943311
0.63537415
0.645804989
0.656235828
0.666666667
0.677097506
0.687528345
0.697959184
0.708390023
0.718707483
0.729138322
0.739569161
0.75
0.760430839
0.770861678
0.781292517
0.791609977
0.802040816
0.812471655
0.822902494
0.833333333
0.843764172
0.854195011
0.86462585
0.875056689
0.88537415
0.895804989
0.906235828
0.916666667
0.927097506
0.937528345
0.947959184
0.958276644
0.968707483
0.979138322
0.989569161

К сожалению, между этими галочками он также посылает мне fake ticks, которые не кратны оригиналу pulses, Такие как 0,029024943, который является кратным 256, которого нет в списках импульсов.

Как я могу найти из этого списка, какие галочки valid и которые fake?
У меня нет списка импульсов для сравнения во время процесса, так как 8820 будет меняться со временем, поэтому у меня нет списка для сравнения шаг за шагом. Мне нужно выводить это из галочек на каждой итерации.

Какой лучший математический подход к этому? Может быть, рассуждения только в тик, а не пульс.

Я думал найти более близкую ошибку между ближайшим целочисленным импульсом и предыдущим / следующим тиком. Вот в C ++:

double pulse = tick * 96.;
double prevpulse = (tick - 1/8820.) * 96.;
double nextpulse = (tick + 1/8820.) * 96.;

int pulseRounded=round(pulse);
int buffer=lrint(tick * 8820.);

double pulseABS = abs(pulse - pulseRounded);
double prevpulseABS = abs(prevpulse - pulseRounded);
double nextpulseABS = abs(nextpulse - pulseRounded);

if (nextpulseABS > pulseABS && prevpulseABS > pulseABS) {
// is pulse
}

но например галочка 0.0417234 (пульс 368) терпит неудачу, так как ошибка предыдущего тика, кажется, ближе, чем она: prevpulseABS ошибка (0.00543795) меньше чем pulseABS ошибка (0.0054464).

Это потому что это сравнение не заботится о округлении, я думаю.

2

Решение

НОВЫЙ ПОСТ:

Хорошо. Исходя из того, что я теперь понимаю, вот мой пересмотренный ответ.

У вас есть информация, необходимая для составления списка хороших ценностей. Каждый раз, когда вы переключаетесь на новый трек:

vector<double> good_list;
good_list.reserve(96);
for(int i = 0; i < 96; i++)
good_list.push_back(BankerRound(8820.0 * i / 96.0) / 8820.0);

Затем каждый раз, когда вы хотите проверить ввод:

auto iter = find(good_list.begin(), good_list.end(), input);
if(iter != good_list.end()) //It's a match!
cout << "Happy days! It's a match!" << endl;
else
cout << "Oh bother. It's not a match." << endl;

Проблема с математическим определением правильных импульсов заключается в функции BankerRound (), которая будет вносить постоянно растущую ошибку при введении более высоких значений. Тогда вам понадобится формула для формулы, и это выходит из моей рубки. Или вы можете отслеживать различия между последовательными значениями. Большинство из них будут одинаковыми. Вам нужно только проверить между двумя возможными ошибками. Но это развалится, если вы можете прыгать треки или прыгать по одной дорожке.

СТАРЫЙ ПОСТ:

Если я правильно понимаю вопрос, единственная информация, которую вы получаете, должна поступать в форме (p / v = y), где вы знаете «y» (это каждый элемент в вашем списке тиков, которые вы получаете с устройства) и Вы знаете, что «p» — это импульс, а «v» — это «Значения на удар», но вы не знаете, что из них является. Итак, вытащив одну точку данных из вашего поста, вы можете получить уравнение, подобное этому:

p / v = 0,010430839

‘v’ во всех приведенных выше примерах составляет 8820, но, насколько я понимаю, это значение не является гарантированной константой. Следующий вопрос: есть ли у вас способ определить, что такое «v», прежде чем вы начнете получать все эти десятичные значения? Если вы это сделаете, вы можете математически определить, какая наименьшая ошибка может быть (1 / v), затем взять свою десятичную информацию, умножить ее на ‘v’, округлить до ближайшего целого числа и проверить, чтобы увидеть разницу между округленными форма и ее не округленная форма попадают в пределы вашей вычисленной ошибки следующим образом:

double input; //let input be elements in your list of doubles, such as 0.010430839
double allowed_error = 1.0 / values_per_beat;
double proposed = input * values_per_beat;
double rounded = std::round(proposed);
if(abs(rounded - proposed) < allowed_error){cout << "It's good!" << endl;}

Если, однако, вы не возможность определить значения values_per_beat заранее, тогда это становится статистическим вопросом. Вы должны накопить достаточное количество выборок данных, удалить выбросы (те, которые отличаются от нормы) и использовать эти данные. Но этот подход не будет в реальном времени, который, учитывая термины, которые вы использовали (значения на удар, ударов в минуту, значение 44100), звучит так, как будто в реальном времени вы захотите.

1

Другие решения

Играя с Excel, я думаю, вы хотите умножить до (что должно быть) целые числа, а не искать самые близкие импульсы.

Tick                Pulse                   i   Error                           OK
Tick*8820       Pulse*96/8820   ABS( i - INT( i+0.05 ) )    Error < 0.01
------------    ------------    -------------   ------------------------    ------------
0.029024943     255.9999973     2.786394528     0.786394528                 FALSE
0.0417234       368.000388      4.0054464       0.0054464                   TRUE
0                 0             0               0                           TRUE
0.010430839      91.99999998    1.001360544     0.001360544                 TRUE
0.020861678     184             2.002721088     0.002721088                 TRUE
0.031292517     275.9999999     3.004081632     0.004081632                 TRUE
0.041723356     367.9999999     4.005442176     0.005442176                 TRUE
0.052040816     458.9999971     4.995918336     0.004081664                 TRUE
0.062471655     550.9999971     5.99727888      0.00272112                  TRUE
0.072902494     642.9999971     6.998639424     0.001360576                 TRUE
0.083333333     734.9999971     7.999999968     3.2E-08                     TRUE

В таблице показаны два ваших «проблемных» случая (реальное неверное значение 256 и тот, в котором ваш код ошибается 368), за которыми следуют первые несколько «хороших» значений.

Если оба 8820изменяются в то же время, то, очевидно, они будут отменены, и i просто будет Tick*96,

Error срок — это разница между рассчитанным i и ближайшее целое число; если это меньше чем 0.01тогда это «хорошая» ценность.

Обратите внимание 0.05 а также 0.01 значения были выбраны произвольно (так называемое первое предположение, основанное на числах): скорректируйте при необходимости. Хотя я показал только первые несколько строк, все 96 «хороших» значений, которые вы дали, показывают как ИСТИНА.

Код (полностью непроверенный) будет выглядеть примерно так:

double pulse = tick * 8820.0 ;
double i = pulse * 96.0 / 8820.0 ;
double error = abs( i - floor( i + 0.05 ) ) ;
if( error < 0.05 ) {
// is pulse
}
0

Я предполагаю, что вы инициализируете свои импульсы в цикле, используя int i как переменная цикла; тогда проблема в этой строке:

BankerRound(8820 * i/96);

8820 * i / 96 является целочисленной операцией, и результат снова является целым числом, обрезая остаток (так, по сути, всегда округляя до нуля), и BankerRound фактически больше нечего округлять. Попробуйте это вместо этого:

BankerRound(8820 * i / 96.0);

Та же проблема применяется, если вы пытаетесь вычислить предыдущий и следующий импульс, так как вы фактически вычитаете и добавляете 0 (снова, 1/8820 все целое число и приводит к 0).

Редактировать:

Из того, что я прочитал из комментариев, «система» не является, как я предполагал ранее, модифицируемой. На самом деле, он рассчитывает тики в виде

N / 96,0, N &# x220a [0, 96) в ℕ

однако, включая некоторое внутреннее округление, по-видимому, независимое от частоты дискретизации, поэтому есть некоторая разница с истинным значением n / 96.0, и тики, умноженные на 96, не дают точно интегральные значения в [0, 96) (спасибо KarstenKoop) , И некоторые из доставленных образцов просто недействительны …

Таким образом, задача состоит в том, чтобы определить, достаточно ли близок тик * 96 к целочисленному значению, чтобы быть принятым как действительный.

Итак, нам нужно проверить:

double value = tick * 96.0;
bool isValid
=  value - floor(value) < threshold
|| ceil(value) - value  < threshold;

с некоторым соответствующим образом определенным порогом. Предполагая, что значения действительно рассчитываются как

double tick = round(8820*i/96.0)/8820.0;

тогда максимальное отклонение будет немного больше, чем 0,00544 (более точное значение см. ниже), пороговые значения где-то в размере 0,006, 0,0055, 0,00545, … могут быть выбраны.

Округление может быть связано с внутренним количеством битов для значения датчика (если у нас есть 13 доступных битов, тики могут фактически рассчитываться как floor(8192 * i / 96.0) / 8192.0 с 8192 1 << 13 &ndash и минимальный учет до целочисленного деления; просто предположение…).

Точное значение максимального отклонения с использованием 8820 в качестве фактора, столь же точного, что и представляемое двойным, было:
0,00544217687075132516838493756949901580810546875

Умножение на 96 на самом деле не является необходимым, вы можете сравнить непосредственно с порогом, деленным на 96, который будет:
0,0000566893424036596371706764330156147480010986328125

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector