« first day (1314 days earlier)      last day (1717 days later) » 

1:56 AM
Какая есть замена для BitArray , которая действиельно бы хранила "массив бит", а не занималась самодеятельностью с порядком бит
 
 
5 hours later…
7:22 AM
@vitidev о чем вы? как еще можно хранить биты, если не в байтах
int, соответственно 32 бита
почему именно int выбрали? думаю, что он быстрее, чем byte
 
 
1 hour later…
8:33 AM
@АндрейNOP Я ожидаю от BitArray, что он будет хранить биты "как ему дали", а не по своему.
 
@vitidev что вам не нравится здесь:
public BitArray(bool[] values)
{
	m_array = new int[GetArrayLength(values.Length, BitsPerInt32)];
	m_length = values.Length;

	for (int i = 0; i < values.Length; i++)
		if (values[i])
			m_array[i/32] |= (1 << (i%32));
}
?
 
            //у нас есть биты
            var v1 = new[] { 1, 1, 1, 0, 0, 0, 0, 0 };

            //делаем BitArray
            var v2 = v1.Select(v => v > 0).ToArray();
            var bitArray1 = new BitArray(v2);

            //хотим преобразовать в число
            //ожидаю что он выдаст байты в которых биты в том же порядке
            var b = new byte[1];
            bitArray1.CopyTo(b, 0);

            //в b[0] биты реверсированы
 
Console.WriteLine(b[0]);
> 7
куда они реверсированы?
v1[0] - нулевой бит, он равен 1
также v1[1] = 1 и v1[2] = 1
итого 1+2+4=7
всё верно
 
вот только у 7 биты 00000111, что полностью отличается от исходного 11100000
 
не отличается, просто это вы так читаете, что у вас старшие разряды левее младших
непонятная претензия в общем
или вы как-то не так хотите это использовать
 
8:46 AM
я знаю про LE/BE но я ожидаю полноценной работы с битами "как их дали в том же порядке" судя по названию BitArray, а не NumWithBitArray
 
@vitidev при чем тут вообще LE/BE? они тут как раз не влияют
когда вы пишете var v1 = new[] { 1, 1, 1, 0, 0, 0, 0, 0 }; у вас нулевой бит в начале строки
когда вы выводите двоичное представление числа, у вас нулевой бит в конце строки
компьютер не виноват, что в привыкли так читать
 
@АндрейNOP вообщето виноват. есть всякие битовые маски, где порядок бит неважно в каком числе будет ибо важен само порядок слева направа. и порядок нужно беречь. А он по факту хранит их как числа по своему полностью нарушая в итоге порядок каждых 8 битов
 
@vitidev давайте конкретный пример
если вы попросите вывести римскую запись числа, это не значит, что это число будет храниться в памяти как-то по другому
почему вы вообще завязываетесь на строковое представление?
7 & 0b00000001 = 1
это и есть нулевой бит
7 & (1 << 1) = 1
это первый бит
7 & (1 << 4) = 0
это четвертый и т.д
 
потому что мне важно строковое представление. для этого я этот класс и беру как бы чтобы работать с маской битов как они есть
я ж дал. правда усеченый
у меня тут 64 бита в реальности
var v1 = new[] { 1, 1, 1, 0, 0, 0, 0, 0 ,,,,};
я кормлю их BitArray как набор bool (тамтакой конструктор)

далее я вдруг хочу их сохранить в число в котором будет тот же порядок битов что задано. И тут засада, ведь каждые 8 бит развернуты и нужно их вручную разворачивать (что как бы еще "как") чтобы вернуть все в норму (как еще это задетектить то)
 
    var v1 = new[] { 1, 1, 1, 0, 0, 0, 0, 0 };
                     0  1  2  3  4  5  6  7

у 7 биты 00000111
         76543210
всё совпадает, ничего не перевернуто
 
8:57 AM
у 1, 1, 1, 0, 0, 0, 0, 0 и 00000111 другой порядок битов же
 
new[] { 1, 1, 1, 0, 0, 0, 0, 0 } это массив, какой у него порядок битов?
порядок элементов совпадает с битовым представлением 7
 
вот такой у него порядок
v1.Select(v => v > 0).ToArray();
то есть
new[] { true, true, true, false, false, false, false, false }
 
v1[0] = 1 и 7.ПолучитьБит(0) = 1
что отличается?
 
отличается когда у меня 64 бита (что влазят в long) и я делаю преобразование в лонг
var num = BitConverter.ToInt64(b, 0); где b тот самый массив
то потом
Convert.ToString(num, 2);
выдает перевернутое все
я не могу так просто перейти от порядка битов к числу выражающему тот же порядок битов слева направо
мне приходится доставать бубен, а это не то что я ожидаю от "массива бит". от "массива бит" я ожидаю что он будет держать порядок "слева направо"
то есть вообще "порядок заданных ему бит"
 
вы не правы
v1[0] = 1 и bitArray1[0] = 1, на этом этапе пока нормально?
или уже и здесь вам что-то не нравится?
 
9:07 AM
на этом да. Но повторюсь - мне нужно совержить преобразование в long и тут уже приходится писать кастомные функции с математикой потому что CopyTo выдаст реверс
 
@vitidev ну для начала можно сделать v1.Reverse(), а потом всё остальное
но в любом случае, компьютеру всё равно как вы читаете числа, от старшего разряда к младшему или наоборот, это чисто реализация ToString, на само представление числа в памяти это никак не влияет
 
@АндрейNOP нельзя. v1 суть порядок слева направо. с ним и работать нужно так. это не число, а биты в каком то порядке (по факту порядок true/false). в общем то я и работаю с ними так без всяких BitArray ибо толку нет.
ToString тут вообще не причем. его нет у BitArray
у Convert есть да. но разворачивает не он
BitArray Class

Manages a compact array of bit values, which are represented as Booleans, where true indicates that the bit is on (1) and false indicates the bit is off (0).


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

только вот зачем тогда этот класс, если обычный массив true/false суть то же самое
ну ладно для "битовых" операций
но как потом в результате достать результат не теряя порядка
кастомный метод через енумератор что ли
а зачем тогда BitArray.CopyTo(Array, Int32) Method если он выдаст байты в каждом из которых порядок битов не совпадает с оригинальным порядком
 
10:03 AM
@vitidev приведи конкретный пример, где, по-твоему, порядок не совпадает
 
@Grundy ну хотя бы вот stackoverflow.com/questions/9066831/…
 
@vitidev вроде все правильно :-) в чем не совпадение?
можно даже сказать: все согласно документации :)
@vitidev кстати весьма странный вопрос там. Если bit array - это массив, почему при обходе в for он должен обходиться с конца?
 
ну "написано в документации" не делает поведение разумным.
суть простая.
1 имеем набор false/true (как написано в документации)
2 кормим им BitArray (как написано в документации)
3 если мы пройдем foreach все совпадет

но вот когда мы заходим преобразовать в число с **таким же порядком** бит как изначально было true/false то идем в гугл и находим примеры с CopyTo которые выдают совсем не то
 
> 1 имеем набор false/true (как написано в документации)
2 кормим им BitArray (как написано в документации)
3 если мы пройдем foreach все совпадет
на этом стоит и закончить :-) это стандартное поведение все логично
но вот когда мы заходим преобразовать в число с таким же порядком бит как изначально было true/false то идем в гугл и находим примеры с CopyTo которые выдают совсем не то - ну вот и приведи конкретный пример, где выдано совсем не то
 
10:22 AM
//у нас есть биты
var v1 = new[] { 1, 1, 1, 0, 0, 0, 0, 0 };

//делаем BitArray
var v2 = v1.Select(v => v > 0).ToArray();
var bitArray1 = new BitArray(v2);

//хотим преобразовать в число
//ожидаю что он выдаст байты в которых биты в том же порядке
var b = new byte[1];
bitArray1.CopyTo(b, 0);

в b[0] будет лежат 00000111 , а значит CopyTo нельзя использовать для преобразования в число с таким же "четким порядком бит слева направо "и приходится городить свой огород с циклом
когда я кормлю BitArray числами, то понятно что порядок трансляции числа в порядок бит определен LE/BE на машине
а вот когда я кормлю его четко заданным порядком, то и ожидаю что он его сбережет, но он его не бережет. Он внутри себя хранит как ему удобно, а CopyTo выдает его внутреннее хранение, которое может быть и полезно для восстановления в чеще один BitArray (не проверял)
но c помощью Convert уже не получить строку с нужным порядком 11100000

все понятно, но не очень удобно
 
> когда я кормлю его четко заданным порядком, то и ожидаю что он его сбережет, но он его не бережет.
но ведь он бережет
 
@Grundy ага. в енумераторе или индексаторе. а внутри себя он с радостью переворачивает порядок потому что "так описано в доке, что вот так он хранит" )
 
@vitidev какая разница как он хранит внутри себя? на результат это не влияет
 
пришлось создать метод расширение который в цикле проходит по BitArray и создает нужное число которое потом Convert конвертит в изначальную "11100000"
 
10:48 AM
> в b[0] будет лежат 00000111
там будет лежать число 7
именно то, которое ты и положил в bit array
 
нет. я ложил туда 11100000
new[] { 1, 1, 1, 0, 0, 0, 0, 0
 
@vitidev ну, все правильно :-) ты положил туда биты соответствующие числу 7
 
@Grundy нет. я положил биты. а он решил их распарсить и хранить как число 7, а не 224
 
@vitidev он их не парсил
он взял их как есть
и то что ты ожидал 224 - на самом деле странно, потому что нулевым битом у этого числа является 0, а не 1, которую ты передал.
 
ему дали 1110000 и он взял их в 7
а когда попросили отдать то он отдал 7
а когда попросили Convert "а ну переведи 7 в биты по нотации в машине" и он отдал 00000111
 
10:57 AM
@vitidev ToString выводи в удобном для человека виде
 
@Grundy ToString у кого?
у BitArray TOString() выдает System.Collections.BitArray
 
@vitidev у Convert очевидно. или ты какой метод у него вызывал чтобы получить 00000111? Причем непонятно что это такое, число или строка?
 
я про Convert.ToString(value, 2);
 
@vitidev и я про него :)
 
и как я ему скажу как выводить?
 
11:03 AM
@vitidev никак, он выводит в понятном для человека виде, а именно когда сначала идут старшие разряды. А вводишь ты в машинном виде, когда сначала заполняешь младшие разряды. Все решается простым Reverse перед передачей в конструктор BitArray - и результат становится таким как ты ожидал (в примере выше 224 вместо 7)
 
если я сделаю Reverse ПЕРЕД вводом в BitArray то я потеряю порядок, а собственно сохранение порядка и важно
 //у нас есть биты
            var v1 = new[] { 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 };

            //делаем BitArray
            var v2 = v1.Select(v => v > 0).ToArray();
            var bitArray1 = new BitArray(v2);

            //работаем работаем

            //хотим преобразовать в число
            // гуглим
            var bytes = new byte[2];
            bitArray1.CopyTo(bytes, 0);

            //теперь в число.
            var number = BitConverter.ToInt16(bytes, 0);

            //теперь у нас есть число. можем ли мы получить оригинальный порядок битов
 
> //не можем
stringbits: 0000011100000111
а это разве не оригинальный?
 
оригинальнй от числа что вернул BitConverter - да
но нужно получить оригинальные new[] { 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 }
 
@vitidev еще раз: вывод происходит в понятном для человека виде, а именно когда сначала идут старшие разряды. А вводишь ты в машинном виде, когда сначала заполняешь младшие разряды. Все решается простым Reverse перед передачей в конструктор BitArray - и результат становится таким как ты ожидал (в примере выше 224 вместо 7)
Все решается простым Reverse перед передачей в конструктор BitArray либо результирующей строки
 
11:26 AM
еще раз
1 если я разверну порядок перед передачей в BitArray, то BitArray станет для меня бесполезен - ведь ВНЕШНИЙ порядок в нем будет не тот, который все ожидают. А это правильный набор нулей и единиц в правильном порядке а не каком нибудь. Не с числами работаем, а именно с набором битовых/булевых (не суть важно) флагов,

2 но если мы уж загнали наш порядок битов/флагов в BitArray, и хотим преобразовать в компактную форму (число (значимый тип) ) и потерять BitArray, то мы должны делать дополнительные шаги потому что преобраузется по гуглению в то, из чего Convert.ToString( сделает совсе
 
@vitidev тогда очевидно Reverse полученной строки :-) хотя и в текущем виде отображение вполне верное
 
одна машина
Convert говорит что 224 -> 1110000
а BitArray говорит что 1110000 -> 7
 
@vitidev давай еще раз пройдем что говорит каждый из них :-)
в bitarray - ты вводишь начиная с 0 разряда
строка выводится начиная с 7го разряда
потому что для человека привычнее смотреть когда у числа сначала идет старший разряд
как в десятичной системе
 
@Grundy с чего это вдруг. ему передается набор tru/false и даже НЕ кратный 8ми и он в foreach их правильно обходитм
@Grundy вообще не понял
 
@vitidev потому что true и false здесь - это состояние конкретного бита. причем индекс бита соответствует индексу в переданном массиве
на примере в десятичной системе:
12 -> 1*10^1 + 2*10^0
в функцию хранения ты передаешь массив соответствующий коэффициентам перед 10, причем для простоты - индекс элемента совпадает со степенью соответствующей 10

1*10^1 -> коэффициент '1' - степень '1'
2*10^0 -> коэффициент '2' - степень '0'

соответственно массив будет [2,1] - однако при переводе в число будет логичное 12, а не 21 как хотел бы ты.

именно по такому же принципу работает и BitArray
 
11:36 AM
вы про это из документации?

"The first byte in the array represents bits 0 through 7, the second byte represents bits 8 through 15, and so on. The Least Significant Bit of each byte represents the lowest index value: " bytes [0] & 1" represents bit 0, " bytes [0] & 2" represents bit 1, " bytes [0] & 4" represents bit 2, and so on."?
я сломал мозг но так и не понял сути этой ремарки
 
@vitidev поэтому ниже приведен пример для десятичных чисел :)
@vitidev ты почему-то используешь конструктор принимающий массив bool а справку читаешь к конструктору принимающему массив byte
 
@Grundy но я могу передать число бит не кратное 8
 
@vitidev ну и что? :-) это ж bit array - поэтому он битами оперирует :)
 
1110000010
и где у него будет тут что
 
@vitidev а что это? :-)
 
11:53 AM
я спрошу проще. я кормлю BitArray var v1 = new[] { 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 } и он уже создан (так что реверсе до конструктора не предлагать)
и как мне сохранить его в какое нибудь число из которого я смогу потом достать исходный порядок нулей и единиц?
ну кроме варианта с foreach и самосоятельным составлением этого числа
по факту ручной упаковки
 
@vitidev но ведь ты и получаешь именно исходный порядок нулей и единиц
 
где получаю? я получаю число которое в LE нотации (а именно с ней и будут работать все) содержит биты в обратном порядке
 
@vitidev оно содержит биты именно в том порядке, в котором ты его передал
если ты проверяешь порядок бит с помощью ToString - то должен учитывать, что он возвращает строку у удобном для человека виде
 
я передал 1110000. это у нас что? 224
CopyTo вернул мне 7
а это у нас 00000111 это и так понятно даже можно не проверять ToString (впрочем ToString тут полностью солидарен)
 
@vitidev давай проверим что ты на самом деле передал :)
 
11:59 AM
@Grundy и сновы вы возвращаетесь к "а вот он считает так" и уходите от сути вопроса
 
[1,1,1,0,0,0,0] -> 1*2^0 + 1*2^1 + 1*2^3 + 0*2^4 + 0*2^5 + 0*2^6 + 0*2^7 = 7
ты передал битовое представление числа 7
чтобы получить 224 - ты должен был передать [0,0,0,0,0,1,1,1]
 
в этом и есть суть.
вы мне доказываете что "вот ты ему так передал чего ты удивляешься"

а мой вопрос в другом

(имеем 11100000. пишем их как булы)
var bitArray1 = new BitArray(new[] { true, true, true, false, false, false, false, false });

имея на руках готовый bitArray1 нужно получить число, которое в битовой форме будет 11100000
 
@vitidev ну так ты получаешь именно то, что и передал, но продолжаешь упорствовать, что ответ должен быть другим :-) хотя ответ именно тот который и должен быть
@vitidev ты что-то странное хочешь :-) если ты хочешь 11100000 почему ты тогда передаешь в обратном виде? :-)
массив принимаемый конструктором - это биты в обратном порядке, если тебе так будет понятнее :)
var bitArray1 = new BitArray(new[] { true, true, true, false, false, false, false, false }.Reverse());
Решает твою проблему
 
@Grundy это что за математика такая. вбить в любой калькулятор конвертер 11100000 и получим 224
 
@vitidev это перевод числа из одной системы счисления в другую :-)
 
12:07 PM
@Grundy у вас на руках готовый битаррай. забудьте про реверсе до конструктора. вот просто забудьте и все. вот нет его.
@Grundy ну а я чего по вашему хочу?
 
@vitidev ты не знаешь что именно делает внутри калькулятор конвертер - это довольно высокая абстракция, в то время как bitarray довольно низкая
@vitidev пока непонятно чего ты хочешь :-) похоже придумать какую-то свою математику :-)
@vitidev ну так проблема в том. что начальный bitarray - строится неверно, судя по тому, какой результат ты хочешь от него получить
это проблема не bitarray - а кода который его использует
еще раз пример: 11100000 и получим 224
чтобы это сработало должны выполниться следующие условия
 
итак. на машине у нас LE так?
в которой
00000001 - это 1
00000011 - это 3
00000111 - это 7
согласны?
 
@vitidev здесь нет никакого отношения к LE
 
и в которой 11100000 это 224
 
@vitidev подожди допишу пример :)
а то опять скажешь что непонятно :-)
еще раз пример: 11100000 и получим 224
чтобы это сработало должны выполниться следующие условия
1*2^7+1*2^6+1*2^5+0*2^4+0*2^3+0*2^2+0*2^1+0*2^0 = 224
получаем соответствие:
значение бита - индекс в массиве
1 - 7
1 - 6
1 - 5
0 - 4
0 - 3
0 - 2
0 - 1
0 - 0
получаем массив: [0,0,0,0,0,1,1,1]
то что и нужно было передать в конструктор
 
12:17 PM
и почему вдруг такое соотествие
почему он не берет первую true и не кладет его под индексом 0
вторую true и под индексом 1

с чего вдруг первый переданный элемент получил индекс 7
 
@vitidev потому что вот так :-)
 
@Grundy эту математику я понимаю
@Grundy а эту вообще нет.
 
@vitidev а вот эту? :-)
43 mins ago, by Grundy
на примере в десятичной системе:
12 -> 1*10^1 + 2*10^0
в функцию хранения ты передаешь массив соответствующий коэффициентам перед 10, причем для простоты - индекс элемента совпадает со степенью соответствующей 10

1*10^1 -> коэффициент '1' - степень '1'
2*10^0 -> коэффициент '2' - степень '0'

соответственно массив будет [2,1] - однако при переводе в число будет логичное 12, а не 21 как хотел бы ты.

именно по такому же принципу работает и BitArray
для простоты - индекс элемента совпадает со соответствующей степенью основания
 
потому что "так написано в документации"? )
но это и приводит нас к моему вопросу "и как конвертировать содержимое готового битаррай в число, которое любой конвертер/калькулятор/(даже Convert) превратит в оригинальную последовательность"
 
@vitidev использовать Reverse для итоговой строки например. Но, естественно, лучше просто правильно использовать bitarray
если нужен обратный порядок бит - то надо использовать Reverse - очевидно
можно даже на самом bitArray
 
12:21 PM
реверсе для итоговой не подойдет. там не все развернуто, а развернута каждая 8ка (впроем и все тоже)
нет. я этого не понимаю.
12 -> 1*10^1 + 2*10^0 - понимаю
>ты передаешь массив соответствующий коэффициентам перед 10,

чего чего я передаю?
 
@vitidev это пример для основания 10
при работе с битами - основание 2
@vitidev у тебя все в кучу смешало
если у тебя первый bitarray строится неверно и ты не можешь изменить его создание, ты можешь создать свой bitarray с обратным порядком бит
var bitsArray2 = new BitArray(bitArray1.Cast<bool>().Reverse().ToArray());
 
не только у меня. на со полно вопросов на эту тему правда на англ. впрочем я и на ру в этом чате пока только больше запутался. Понял одно что он кладет под другими индексами и потом когда делает CopyTo то просто по этим индексам и вычитывает и получается "разворот"

а вот почему зачем так делать я не понял
как и не понял магии
1,1,1,0,0,0,0] -> 1*2^0 + 1*2^1 + 1*2^3 + 0*2^4 + 0*2^5 + 0*2^6 + 0*2^7 = 7
 
@vitidev тут нет магии
тут напрямую хранятся биты на соответствующих позициях
обрати внимание, что степень двойки соответствует индексу элемента, значение которого используется в качестве коэффициента
 
но зачем это. что это дает?
 
@vitidev простой способ для перевода в другие системы счисления
 
12:33 PM
так а в чем же он простой если мы из 224(1110000) не можем потом по простому получить эти 224
 
@vitidev а как ты хочешь получить 224 из 1110000?
опиши свои действия
 
вот же ваше

1*2^7+1*2^6+1*2^5+0*2^4+0*2^3+0*2^2+0*2^1+0*2^0 = 224
 
@vitidev именно
откуда у тебя взялась степень 7 для первой двойки?
 
индекс в LE нотации
 
@vitidev индекс где? :)
в массиве?:)
вот и пришли что индекс первой единицы в массиве должен быть 7 :)
 
12:39 PM
так так так
щас попробую ухватить мысль
в LE нотакции 224 это
1 - 7
1 - 6
1 - 5
0 - 4
0 - 3
0 - 2
0 - 1
0 - 0
справа индексы
и получется он так и хранит
но при CopyTo он наинает обходить ПО ИНДЕКСУ 0-7 при упаковке в целевой байт и потому в байт последовательно попадает 00000111
 
@vitidev можно даже посмотреть что именно он делает в CopyTo
@vitidev в байт как раз попадет 11100000 -> 224
 
byte [] b = (byte[])array;
for (int i = 0; i < arrayLength; i++)
b[index + i] = (byte)((m_array[i/4] >> ((i%4)*8)) & 0x000000FF); // Shift to bring the required byte to LSB, then mask
вот это делает.
магия какая то
 
@vitidev это просто потому что внутреннее представление хранит в массиве int :-)
поэтому идет разворачивание одного числа в 4
 
ну я ж и говорю что он вываливает внутреннее представление в котором изначальный порядок бит перевернут. и это путает. его внутреннее хранение не совпадает с внешним (через foreach) порядком битов
 
@vitidev внутреннее представление он не вываливает :-) обход foreach совпадет с обходом массива bool переданного в конструкторк
 
12:53 PM
значит все дело в упаковке булов
           for (int i = 0;i<values.Length;i++) {
                if (values[i])
                    m_array[i/32] |= (1 << (i%32));
            }
я не могу распарсить в голове это потому проще дебагом пройтись
 
@vitidev ну тут все просто по одному биту выставляется для каждого из int
 
он хранит в интах. в конструкторе с интами вообще тупой Array.Copy
в булах же строка
m_array[i/32] |= (1 << (i%32));

как я понимаю заталкивает 11100000 как (в скобках индексы байт первого инта в котором он хранит) [0]11100000 [1]00000000 [2]00000000 [3]00000000
в какой момент вдруг 11100000 превращается в 00000111
 
1:14 PM
@vitidev ни в какой
ты продебажил что именно выполняется в конструкторе?
 

« first day (1314 days earlier)      last day (1717 days later) »