2013-04-06 5 views
5

Я работаю над встроенным проектом, где мне нужно записать значение тайм-аута в два байтовых регистра некоторых микрочипов.Разделить целое число на два байта

Тайм-аут определяется как:

timeout = REG_a * (REG_b +1) 

Я хочу запрограммировать эти регистры с помощью целого числа в диапазоне от 256 до 60000. позволяет сказать, что я ищу, для которого алгоритма, учитывая timeout- значение, вычисляет REG_a и REG_b.

Если точное решение невозможно, я хотел бы получить следующее возможное большее значение тайм-аута.

Что я сделал до сих пор:

Мое текущее решение вычисляет:

temp = integer_square_root (timeout) +1; 
    REG_a = temp; 
    REG_b = temp-1; 

Это приводит к значениям, которые хорошо работают на практике. Однако я бы хотел, чтобы вы могли придумать более оптимальное решение.

О, и я ограничена памятью, поэтому большие таблицы не могут быть и речи. Также важно время работы, поэтому я не могу просто переустановить решение.

+0

Вы хотите минимизировать разницу между 'timeout' и вычисленным значением? Это цель этого упражнения? В противном случае то, что у вас есть, кажется прекрасным. –

+0

Одним из вариантов оптимального является минимизация одного регистра и максимизация другого. Возможны проблемы с этим интерфейсом регистра, где вы не хотели бы менять оба регистра внезапно. Поскольку вы не можете одновременно записывать две записи, могут возникнуть проблемы, если регистры записаны **, когда ** работает таймер. Минимизируя один регистр, вы можете оставить его одинаковым при переходе на меньший тайм-аут, поскольку минимум дает лучшую временную детализацию. –

ответ

2

Вы можете использовать код, используемый в этом ответе Algorithm to find the factors of a given Number.. Shortest Method?, чтобы найти коэффициент тайм-аута.

n = timeout 
initial_n = n 
num_factors = 1; 
for (i = 2; i * i <= initial_n; ++i) // for each number i up until the square root of the given number 
{ 
    power = 0; // suppose the power i appears at is 0 
    while (n % i == 0) // while we can divide n by i 
    { 
     n = n/i // divide it, thus ensuring we'll only check prime factors 
     ++power // increase the power i appears at 
    } 
    num_factors = num_factors * (power + 1) // apply the formula 
} 

if (n > 1) // will happen for example for 14 = 2 * 7 
{ 
    num_factors = num_factors * 2 // n is prime, and its power can only be 1, so multiply the number of factors by 2 
} 
REG_A = num_factor 

Первый фактор будет ваш REG_A, так, то вам нужно найти другое значение, умноженное равно тайм-аут.

for (i=2; i*num_factors != timeout;i++); 
REG_B = i-1 
1

Интересная проблема, Нилс!

Предположим, что вы начинаете с фиксации одного из значений, например Reg_a, затем вычисляете Reg_b путем деления с округлением: Reg_b = ((timeout + Reg_a-1)/Reg_a) -1.

Знаете ли вы, что вы близки, но как близко? Ну, верхняя граница ошибки будет Reg_a, правильно? Потому что ошибка - это остальная часть деления.

Если вы сделаете один из факторов как можно меньшим, тогда вычислите другой коэффициент, вы должны сделать эту верхнюю границу ошибки как можно меньше.

С другой стороны, сделав два фактора близко к квадратному корню, вы делаете делитель как можно большим и, следовательно, делаете ошибку максимально возможной!

Итак:

Во-первых, то, что минимальное значение для Reg_a? (timeout + 255)/256;

Затем вычислите Reg_b, как указано выше.

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

Смежные вопросы