C # - 1 2 4 8 16 32 64 серии - Найти индексы на основе входного числа, рекурсивная функция?

У меня есть ряд чисел как таковой: [1 2 4 8 16 32 64 128], если я ввожу число, т.е. 66, то на выходе должно быть 64 и 2. Если я ввожу 87, то на выходе должно быть 64, 16, 4, 2, 1.

(По сути, сначала нужно разделить на максимально возможное число, найти остаток, затем продолжить деление на максимально возможное число, пока остаток не станет равным 0. Или другим способом, может быть, просто вычесть максимально возможное число и продолжать вычитать, пока не достигнет 0.)

Я думаю о рекурсивной функции, но не совсем уверен. Любая помощь?

Спасибо.


person Saxman    schedule 30.03.2011    source источник
comment
Вы рассматривали возможность добавления тега домашнего задания? :)   -  person Marek    schedule 30.03.2011
comment
Подумайте о бинарном.   -  person Dykam    schedule 30.03.2011
comment
Если это домашнее задание, открыто говорите об этом. Это можно решить либо итеративно, либо рекурсивно, и вам придется решить, какой из них (вы не даете нам никаких причин, почему вы думаете рекурсивно). Попробуйте написать свою программу. Если у вас возникнут проблемы, вернитесь сюда и опубликуйте свой код и укажите, что именно пошло не так. Это дает нам наилучшую возможность помочь вам.   -  person David Thornley    schedule 30.03.2011
comment
что касается этой серии чисел - это всегда степень 2 (в этом случае вам даже не нужно ее хранить) или вы хотите, чтобы она работала для любой произвольной серии?   -  person jon_darkstar    schedule 30.03.2011
comment
:) Это вовсе не домашнее задание... хотя оно связано с клиентом, я работаю над приложениями, чтобы выделить столбцы ошибок на основе числа, возвращенного из базы данных, и этот номер битов ошибки основан на этой серии чисел. . Спасибо.   -  person Saxman    schedule 30.03.2011
comment
@Saxman, язвительный упрек за то, что настоящая работа интерпретируется как вопрос домашнего задания! Как говорит Дайкам, если речь идет о степенях двойки, наилучшим подходом является двоичное представление, поскольку двоичное представление скажет вам, какая комбинация степеней дает результат.   -  person Steve    schedule 10.01.2018


Ответы (7)


Вот итерационная версия

public static IEnumerable<int> FindIndex(int input)
{
    var power = 0;
    while (input > 0)
    {
        var digit = input % 2;
        if (digit == 1)
        {
            yield return (int)Math.Pow(2, power);
        }
        input /= 2;
        power++;
    }
}

а вот рекурсивная версия

public static void FindIndexRec(int input, int power, ICollection<int> numbers)
{
    if (input == 0)
    {
        return;
    }
    var digit = input % 2;
    if (digit == 1)
    {
        numbers.Add((int)Math.Pow(2, power));
    }
    FindIndexRec(input / 2, ++power, numbers);
}

и вы можете назвать это как

var numbers = new List<int>();
FindIndexRec(input, 0, numbers);
person Petar Petrov    schedule 30.03.2011

Вы можете использовать битовые маски. На самом деле, зачеркните это - вы должны использовать битовые маски! Почти наверняка именно так был создан код ошибки, и именно так его следует разобрать. Все остальное, скорее всего, смутит вашу аудиторию других программистов.

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

Нет необходимости даже где-либо сохранять результат, так как его можно быстро пересчитывать каждый раз, например так:

for(int i=0;i<8;++i) {
    if((error&(1<<i))!=0 {
        // 1<<i is in the resulting list.
    }
}
person Community    schedule 30.03.2011

Вот довольно наивное итерированное решение в псевдокоде. Попробуйте взять отсюда куда-нибудь поинтереснее. Вы можете сделать это рекурсивно, вы можете преобразовать целое число в двоичное представление и выполнить итерацию по этой строке, я думаю, есть умный способ сделать это с помощью LINQ очень лаконично и т. д.

v = inputNumber
while(v > 0):
     temp = greatest power of 2 less than v
     print temp
     v -= temp

PS - это явно не хранит рассматриваемую серию - это предполагает степени 2.

person jon_darkstar    schedule 30.03.2011

Этот будет работать с входными числами больше 256:

   int[] calculate(int input)
    {
        List<int> retVal = new List<int>();
        string output = string.Empty;
        int[] series = new int[] { 1, 2, 4, 8, 16, 32, 64, 128 };
        foreach (int i in series.Reverse<int>())
        {
            while (input >= i)
            {
                retVal.Add(i);
                input -= i;
            }
        }

        return retVal.ToArray();
    }

Пример: var результат = вычислить (284); // результат = 128, 128, 16, 8, 4

person Joe    schedule 30.03.2011

    IEnumerable<int> GetFlags(int input,IEnumerable<int> series)
    {
        foreach (int value in series)
            if ((input & value)==value)
                yield return value;
    }

Или LINQ решение проблемы.

IEnumerable<int> GetFlags(int input, IEnumerable<int> series)
{
    return series.Where(x => (x & input) == x);
}
person Ali Bayat    schedule 10.01.2018

Помимо программирования, вы также можете взглянуть на это математически. Это в основном 2 в степени (целочисленное значение) log(2, input)

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

person martin k.    schedule 10.01.2018

person    schedule
comment
+1 хорошая идея использовать перечисление (но в заголовке упоминается отказ) - person MaLio; 30.03.2011
comment
очень красиво, я не подумал об этом. я не очень хорошо знаю С#, можете ли вы каким-то образом использовать макрос для этого перечисления? тогда это было бы действительно милое решение - person jon_darkstar; 30.03.2011
comment
+1, вам нужен атрибут flags в перечислении, чтобы это работало? - person Joe; 30.03.2011
comment
@Joe: да, вам нужен атрибут, чтобы он принимал его побитно :) - person František Žiačik; 30.03.2011
comment
@jon_darkstar: Боюсь, это нельзя сделать макросом, по крайней мере, я не знаю, как это сделать. - person František Žiačik; 30.03.2011