Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа с битами
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
sheka
Хочется видите ли с битами работать. Но даже в тот же Longint они не влазят.
Вот такой маразм не прокатывает:
program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils;

var
p: pointer;
pSize: integer;
i: integer;

begin
pSize := SizeOf(longint)*8+1;
WriteLn(pSize);
GetMem(p,pSize);
FillChar(p^,pSize,0);
Integer(p^) := 4294967296;
for i := pSize-1 downto 0 do
Write((Integer(p^) shr i)and $1);
WriteLn;
FreeMem(p,pSize);
readln;
end.

Объявлять массив Байтов и делать перегрузку +- не интересно.
IUnknown
Ну, с таким-то значением ничего перегружать не надо:
type
PInt64 = ^Int64; // Можно работать и с QWord, причем безо всяких извращений с выделением памяти...
var
p : pointer;
pSize : integer;
i : integer;
begin
pSize := SizeOf(longint)*8+1;
WriteLn(pSize);
GetMem(p,pSize);
FillChar(p^,pSize,0);
PInt64(p)^ := 4294967296;
for i := pSize-1 downto 0 do
Write((PInt64(p)^ shr i)and $1);
WriteLn;
FreeMem(p,pSize);
readln;
end.
, а вот если значение будет больше 18446744073709551615 (максимум для QWord - вот тогда точно придется принимать меры)

P.S. Вопрос на засыпку: на кой ты выделяешь 33 байта, если тебе достаточно 33 битов для хранения значения?
sheka
Ну 512бит это уже лучше, но все равно не много smile.gif

Когда игрался с типами забыл 8 убрать.

А есть какой-то битовый тип кроме boolean?
IUnknown
512 бит - это 64 байта, а тип Int64 - это 64 бита...

Цитата
А есть какой-то битовый тип кроме boolean?
Нет. Ко всему прочему, Boolean - ни разу не битовый. То, что он может хранить только 2 значения - еще ни о чем не говорит... Ты задачу-то озвучь, может что-то кроме таких извращений можно будет придумать. Чего ты привязался к битам?

... (Показать/Скрыть)
sheka
Что-то я лишний раз на 8 умножил (логарифм от того большого числа брал).
Но если массив booleanoв, то можно делать приведение типов word(a[i]) и будет выдавать нужный результат при той же занимаемой памяти что и у битов.
Задачу не помню, сродни вот этой Flip, но там надо было как-то передвигать штуки типа японского кроссворда. Обычно из-за того, что не хватает разрядной сетки пользуюсь рекурсией, хотя очень бы хотелось пользоваться такими штуками
IUnknown
Цитата
Но если массив booleanoв, то можно делать приведение типов word(a[i]) и будет выдавать нужный результат при той же занимаемой памяти что и у битов.
Не будет. Либо тебе очень повезло и ты натолкнулся на простое совпадение, либо результат будет, но неправильный. Массив Boolean-ов никогда не занимает в памяти места меньше, чем по 1 байту на значение...

Попробуй показать тестовый код, скажем, который вот так же, как мой напечатает содержимое Integer-а через массив Boolean-ов, при этом места этот самый массив будет занимать ровно 2 байта (как и сам Integer) smile.gif
sheka
Цитата
Не будет. Либо тебе очень повезло и ты натолкнулся на простое совпадение, либо результат будет, но неправильный. Массив Boolean-ов никогда не занимает в памяти места меньше, чем по 1 байту на значение...
Не ожидал. Совсем не ожидал. А почему Boolean занимает ВСЕГДА 1 байт? Зачем оно так?

Это АДА?
Lapp
Цитата(sheka @ 9.07.2011 0:01) *
Не ожидал. Совсем не ожидал. А почему Boolean занимает ВСЕГДА 1 байт? Зачем оно так?

А чего тут ожидать/не_ожидать? Берешь проверяешь, sizeof всегда под рукой.

Идеология простая.
1. Архитектура памяти - байтовая. То есть невозможно адресовать бит в системе команд.
2. Каждая переменная должна иметь свой адрес.

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

У меня когда-то был модуль для побитового доступа к памяти. Сделать его нетрудно. Скорость в те времена падала заметно, сейчас ситуация может быть лучше. Все зависит от того, КАК реализовать )).
sheka
Да это понятно, что sizeof все прекрасно выдает, так и проверял, но почему-то на подсознании думал раз 2 значения, значит бит.
Идеология кого?
Архитектура языка?
И в какую сторону его реализовывать? smile.gif
IUnknown
Цитата
А почему Boolean занимает ВСЕГДА 1 байт? Зачем оно так?
Стоп... Похоже, FPC умеет-таки упаковывать биты (в Дельфи, однако, этого нет до сих пор, хотя просили давно):

type
bit = 0 .. 1;
bitarr = bitpacked array[1 .. 16] of bit;

var
X : word;
i : integer;
ba : bitarr absolute X;
begin
writeln(sizeof(ba));
X := 5458;
for i := 16 downto 1 do //
write(ba[i]);
writeln;
end.
=>
2
0001010101010010



Цитата
Это АДА?
ADA - это Ассоциация Дантистов Америки, а это - Ada smile.gif
Lapp
Цитата(sheka @ 9.07.2011 0:38) *
Идеология кого?
Программирования.

Цитата
Архитектура языка?
Компьютера.

Цитата
И в какую сторону его реализовывать? smile.gif
Ну как.. Нужно тебе 100 бит. Вызываешь процедуру (свою) MakeBitArray(A,100). Она реально заводит массив из 13 байт. Потом ты обращаешья к нему функцией GetBit(A,55): integer, которая дает тебе 55-ое значение из того массива (используя всякие маски).

Но погоди мутить, volvo877 что-то нарыл, похоже..
sheka
Стремный метод однако.
Лучше ничего нет?

Дык получается, что первые 7 бит booleana - вечные 0 ?
Lapp
Цитата(sheka @ 9.07.2011 0:59) *
Дык получается, что первые 7 бит booleana - вечные 0 ?

Это почему?? никто не гарантировал..
IUnknown
Цитата
Дык получается, что первые 7 бит booleana - вечные 0 ?
Кто тебе сказал, что Boolean - это только 0 и 1? Не было такого уговора. False - да, это 0. А вот насчет True ограничений не было:

var
b : boolean;
begin
b := boolean(255);
writeln(b);
writeln(byte(b));
end.

Все, что не 0 - True... Так что не вечные нули. Смотря ка используешь Boolean...

Цитата
Стремный метод однако.
Хм... Тебя не поймешь. То тебе не так, это - не этак. Скажи, что нужно... Лучше bitpacked все равно вряд ли сделаешь...
Lapp
Кроме прочего, если заводишь boolean переменную динамически, в первый момент там все, что угодно. И, как сказал IU (сорри, очень длинно..)), трактуется так: 0 - ложь, не 0 - правда.
sheka
Делфи на такую штуку иероглифы выводит. Не нравится ему писать TRUE если не 00000001 smile.gif

Это-то и нужно, просто это не интересно, до этого даже я додумался smile.gif
Лучше и не надо, меня именно и интересуют извращения, т. е. посмотреть что можно вытащить из возможностей.

Ну как бы в Си такое же понятие True и False, и именно поэтому как зарезервированные слова они появились позже и то в библиотеках, если не ошибаюсь. Зачем тогда было выдумывать boolean? для простой смены True = not False ?
Lapp
Цитата(sheka @ 9.07.2011 1:18) *
Ну как бы в Си такое же понятие True и False, и именно поэтому как зарезервированные слова они появились позже и то в библиотеках, если не ошибаюсь. Зачем тогда было выдумывать boolean? для простой смены True = not False ?
В Си это не понятие, а интерпретация.
Для лучшей типизации.
IUnknown
Цитата
Лучше и не надо, меня именно и интересуют извращения, т. е. посмотреть что можно вытащить из возможностей.
Я б не рекомендовал тебе заниматься подобными извращениями. По той простой причине, что такие вот "финты ушами" мало того, что малопереносимы между разными компиляторами (как ты уже успел убедиться, код, работающий под FPC, не работает при использовании Дельфи), так еще и при выходе новой версии того же компилятора могут быть проблемы (да, достаточно вспомнить те ужесточения, которые были сделаны при переходе от FPC 2.2.x к 2.4.0, многое из того, что было разрешено в ветке 2.2, в ветке 2.4 делать нельзя). Так что тут игра не стоит свеч. Или будешь переписывать код под каждую версию компилятора smile.gif

Цитата
Зачем тогда было выдумывать boolean? для простой смены True = not False ?
Знаешь, в том виде, в котором оно есть в FPC/Дельфи - лучше б этого типа вообще не было. Изначально это задумывалось совсем в другом виде. Вот в Турбо-Паскале более правильная реализация типа Boolean. Тот код, который я приводил в 14-ом сообщении там тоже будет компилироваться, но writeln(byte(b)) выведет не 255, а 1. И любое ненулевое значение, преобразованное к Boolean, также вернется как 1.

Но в Модуле, Haskell-е и Аде еще более корректная реализация: там это именно перечисление, и преобразовать Integer -> Boolean и обратно обычным тайпкастом просто нельзя. Вот именно так это и задумывалось. Хаки - они для программ смертельны...
sheka
Цитата
Но в Модуле, Haskell-е и Аде еще более корректная реализация: там это именно перечисление

Расскажите о перечислениях более подробно: их представление, размер, кол-во элементов.
SizeOf выдает 4байта. Значит кол-во 232?

Интервальный тип округляется к большему целому кол-ву байт, но не больше 8ми?
IUnknown
Цитата
SizeOf выдает 4байта
Ты опять совершаешь ту же самую ошибку. Пойми, что на SizeOf нельзя полагаться, он будет выдавать разные значения в зависимости от
1) режима, в котором происходит компиляция;
2) использования настроек компилятора или директив.

В частности, на размер типа-перечисления влияет использование директивы $PACKENUM (минимальное количество байт, используемое для хранения перечислимых типов) : в режиме совместимости с Дельфи и ТП по умолчанию принимается {$PACKENUM 1}, в режиме MacPas - {$PACKENUM 2}, в остальных режимах - 4 байта...

Да, максимально теперь поддерживается 232 элементов перечисления (значения хранятся как Byte/Word/Longword в зависимости от количества элементов, и от установленного значения PACKENUM, об этом можно почитать в файле prog.pdf: "8.2.4 Enumeration types")

Цитата
Интервальный тип округляется к большему целому кол-ву байт, но не больше 8ми?
Угу. Ибо самый емкий целочисленный тип имеет размер в 8 байт (Int64 или QWord), больше нет смысла выделять под интервал, границы интервала всегда целочисленные (емкость всех остальных перечислимых типов типов все равно меньше, так что их здесь не принимаем во внимание)
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.