Разминка для мозгов: перевод числа из dec в bin

В качестве продолжения рубрики «Разминка для мозгов», хочу предложить тривиальную задачу перевести целое положительное число, которое вмещается в 4 байта, в двоичную систему счисления не используя библиотек STL, битовых операций и т. п., а используя только стандартные встроенные типы. В каждом байте 8 бит, привязки к архитектуре нет. Программа может быть написана по желанию для 1-го, 2-х, 4-х и 8-ми байтовых чисел.
Программа должна:
— запросить ввод целого положительного числа;
— вывести предупреждение и завершить работу, в случае ввода отрицательного числа;
— вывести предупреждение и завершить работу, в случае если число превышает кол-во байтов;
— отобразить число и его эквивалент в двоичной системе счисления
— конечно же программа должна быть максимально лаконичной.

Формулировка задачи нечёткая ((

Что имеется ввиду под «4-х байтовым десятичным числом»? Число в двоично-десятичном коде? Если нет, то слово «десятичное» надо убрать — в байтах оно по любому в двоичном формате. Почему число именно 4-х байтовое? Из-за 32-битной архитектуры? Если да, то такие детали надо оговаривать явно, поскольку решение задачи для 32-битной и 64-битной архитектуры может быть в корне различным.

Что имеется ввиду под «встроенными типами»? Типы, вводимые в STL, считаются встроенными?

PS. В этой задаче самое неприятное — определить, что число не влезает в 4 байта.

Господа, а почему такой пассив? Вроде «Разминка для мозгов» всегда пользовалась популярностью. Или задача не интересная? Или не по зубам??

PS. Улыбнуло уточнение на счёт 8ми бит в байте. За последние лет 'дцать я, честно говоря, не слышал о работающих компьютерах с невосьмибитными байтами. Тем более сомневаюсь, что у кого-то дома стоит рабочая БЭСМ-6 ;)

Для того чтобы сказать, что задача не интересная, нужно попытаться решить эту задачу ;)
А есть еще одна проблема, отсутствие зубов ;)

Череп, лучше решение опубликуй потом в соответствующий раздел, хорошо? Я просто редко слежу за активностью в этом топике.

P.S. Опубликовал ссылку на эту разминку в VK.

beginner, а у тебя собственное решение готово? «Разминка для мозгов» подразумевает, что существует идеальное (или близкое к идеальному) решение и топикстартер его знает.

selevit, пока, как видишь, желающих поразминать мозги нет (( Если через недельку ни кто не разродится, будем смотреть решение от beginner.

#include <iostream>
using namespace std;
int main(){
    setlocale(LC_ALL, "Russian");
    char bit;
    int i,n;
    unsigned long x;
    char rez[33]="                               ";
    cout<<"Введите целое положительное число"<<endl;
    cin>>x;

    i = 31;//последний символ с конца
    while (x>0) {

        bit = x % 2;
        if (bit == 1) {
            rez[i] = '1';
        } else {
            rez[i] = '0';
        }
        --i;
        x = (int) x /2;
    };
    //теперь сдвинем строку в начало
    n = 0;
    while (rez[n] == ' ') {++n;};
    //n - первый значащий символ символ
    for (i = 1; i < n; i++) {
        rez[i-1] = rez[i-1+n];
    };
    rez[n]='\0';
    cout<<rez<<endl;
    getchar();
    getchar();
}

только проверок нет пока с потоками не научился еще работать

и вопросы к ТС

— конечно же программа должна быть максимально лаконичной.

как определить максимальный уровень лаконичности?

тривиальную задачу перевести целое положительное число, которое вмещается в 4 байта, в двоичную систему счисления

исходное число представлено в текстовом виде?

beginner, а у тебя собственное решение готово?

Так точно ;) Собственное, которое ждет объективной критики.

как определить максимальный уровень лаконичности?

Лаконичный — (Викисловарь)

Для программирования — это уменьшение сложности и объема кода.

Возьмем за пример и проанализируем на лаконичность код Антона.
— в программе объявлены пять переменных (вижу потенциал для оптимизации);
— переменные объявлены, по типу магических чисел;
— массив rez объявлен в функции main() (не принципиально, но считаю лучше объявить массив глобально);
— размер массива лучше объявить как константу (33 это тоже магическое число);
— массив rez инициализируется пустой строкой (предлагаю char rez[33] = {0};);
— массив rez объявлен как char (можно оптимизировать);
— ввод в переменную x (предлагаю переписать, дабы не держать в потоке символ нажатия клавиши <Enter>);
— в операторе x = (int) x /2; переменной х однозначно нужно присвоить результат целочисленного деления (не вижу смысла делать явное приведение типов);
— бессмысленный оператор подсчета пустых символов

//теперь сдвинем строку в начало
n = 0;
while (rez[n] == ' ') {++n;};

т.к. нам известно значение переменной i и получить число заполненных элементов массива rez можно просто найдя разность между размером массива и переменной i;
— программа не выполняет, предусмотренные ТЗ, проверки (я могу только предположить сколько «интересного» для рубрики «Лаконичный код» можно было бы там найти);
— предпоследнее условие также не выполнено (введенное значение не выводится на экран);
— в конце концов директива using в этой программе явно лишняя.
Просуммируем вышесказанное и вернемся к вопросу

как определить максимальный уровень лаконичности?

исходное число представлено в текстовом виде?

Croessmah, полет мысли никто не отменял ;)

Разбомбил мой код в пух и прах (антон это я до регистрации), со всеми пунктами согласен )) кроме пункта про магическое 33. Нам же нужна строка из 32 символов и 33й для окончания строки. 4 байта значат 8 * 4 = 32 единички или нолика. Или нет?

AntonF, да и работает ваша программа не корректно.
На ввод нуля не реагирует.
На ввод 1000000 выдает 11110100001, что не есть верно.

Господа, а почему такой пассив?

Ну, господа могут быть очень даже заняты :)

Я предлагаю своё решение (для 4х байт):

#include <iostream>
#include <cstring>

typedef unsigned int udword;
typedef long long qword;

const udword MAX_32_BIT = 0xFFFFFFFF;

int main()
{
    qword num;
    std::cin >> num;

    //Проверка
    if ( num > MAX_32_BIT || num < 0 )
    {
        std::cout << "fuck you" << std::endl;
        return 1;
    }

    //Массив битов для вывода
    char bits[33];
    std::memset( bits, '0', 33 );
    bits[32] = 0;

    std::cout << "dec " << num << " = " ;

    //Формирование значений массива
    int i = 31;
    while( num > 0 )
    {
        bits[i--] = ( '0' + ( num % 2 ) );
        num /= 2;
    }

    std::cout << bits << " bin" << std::endl;

    return 0;
}

porshe, хорошее решение. Единственный недостаток: привязка алгоритма проверки к четырём байтам. Точнее говоря, игра на том, что имеется целый тип данных, который длиннее, чем тип данных проверяемой переменной. Если же поставить условие, что проверяемое число имеет максимально длинный целый тип, то такой фокус уже не пройдёт.

И #include <cstring> — лишний.

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

#include <iostream>

typedef unsigned int udword;
typedef long long qword;

const udword MAX_32_BIT = 0xFFFFFFFF;

void toBin(std::ostream& out, qword n) {
    if (n > 1)
        toBin(out, n / 2);
    out << n % 2;
}

int main()
{
    qword num;
    std::cin >> num;

    //Проверка
    if (num > MAX_32_BIT || num < 0)
    {
        std::cout << "fuck you" << std::endl;
        return 1;
    }

    toBin(std::cout, num);
    std::cout << std::endl;

    return 0;
}

Преимущества. (1) Не зависит от длины типа аргумента. Т.е. функцию перевода в двоичный вид можно легко шаблонизировать. Будет работать и на char и на long long. (2) Компактность.

Особенность. Не выводит лидирующие нули.

Недостатки. (1) Производительность под большим вопросом по сравнению с итерационным методом, поскольку вызов функции, как правило, обходится дороже. Но точный ответ можно получить только профилированием кода. (2) Лишний расход стека. Хотя и кратковременный.

Ещё надо отметить, что все представленные решения таки используют STL, хотя в условиях задачи было указано, что STL применять нельзя. Т.е. фактически, надо ограничиться стандартной библиотекой C — stdio.h.

Если же поставить условие, что проверяемое число имеет максимально длинный целый тип, то такой фокус уже не пройдёт

То есть вы намекаете, что вводимое число может быть «бесконечно» большим, даже не влезающем в unsgined long long? Ну, тогда задача становится больше задачей на длинную арифметику, нежели на перевод dec -> bin :\

И #include <cstring> — лишний.

А как же memset? (proof)

Особенность. Не выводит лидирующие нули.

Ну, не зря же указан максимальный размер 4 байта. Я подумал, что при таком условии, лидирующие нули не будут большим минусом, а даже наоборот — подчеркнут «32х битность» числа.

Кстати, реализация хорошего класса для работы с очень большими целыми (а может и вещественными) — интересная задача для «разминки» :)

Sorry, на memset не обратил внимания.

То есть вы намекаете, что вводимое число может быть «бесконечно» большим, даже не влезающем в unsgined long long?

Ну, типа того.

Ну, тогда задача становится больше задачей на длинную арифметику, нежели на перевод dec -> bin :\

А вот с этим — не согласен. Конечно, для решения можно использовать библиотеку «длинной математики», но если по условиям задачи STL запрещена, то, видимо, и другие библиотеки тоже не приветствуются. Тем более, не входящие в стандартную поставку компиляторов.

Но можно обойтись и стандартными средствами. Например, приём строки и посимвольное преобразование в число с контролем переполнения. Или поразвлекаться с strtoll из cstdlib. Геморрой, конечно, но решаемо.

Не думаю, что реализация библиотеки для «длинной математики» — хорошая задача для «разминки». Это — очень сложная задача. Даже если не брать действительные числа и математических функций с ними.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.