powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Два число в одно и обратно
25 сообщений из 209, страница 8 из 9
Два число в одно и обратно
    #39159500
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давайте отложим в сторону юридические моменты. Это не интересно для sql.ru.

Лучше обсужить способы storage и оперативный доступ.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159522
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TmaytonСпасибо. А сколько времени (мс)у тебя занимает поиск 1 паспорта по этому файлу?
ИМХУ если правильно бинарный поиск реализовать будет быстрее дерева, медленнее биткарты.
По сути это 10-20 чтений с диска по 4 байта. Причем Последние 10 чтений из 1-2 соседних кластеров (если кластер 4 Кб). Т.е. время поиска не больше времени рандомного чтения 10 кластеров.
2 Дима. ИМХО.

10-20 чтений с диска (random seek, они-же IOPs) это очень много и очень дорого.
Если-бы эти 96 млн записей лежали в B+Tree дереве на диске то нам понадобилось-бы 2-3
уровневое дерево или 2-3 операции чтения блоков. Но автор топика уже слышал советы бывалых БД-шников
и для себя определил что своя кастомная структура лучше. Ну что-ж. Пускай так.

2 All

По поводу биткарт. Я возможно иногда не совсем ясно выражаю свою мысль. Когда я говорю "биткарта Блума"
я имею в виду фильтр Блума (ФБ). И это не есть биткарта в общем понимании этого слова. И ее размер
не определяется количеством элементов. (Я на всякий случай уточняю). Вообще по последнему пункту
я экспериментировал. Я искал некое золотое соотношение качества и количества элементов которо
позволяет сериализовать все паспорта и причём без ложно-положительных срабатываний. Это
сделать можно но для счётного числа ключей вообще.

Для нашей-же задачи фильтр можно наполнить (метафорически это ближе к обучению НС) обучающей выборкой
в 96 млн ключей. При этом теоретическая верхняя граница это



Десять в десятой это десять миллиардов потенциально возможных числовых ключей. Буквенные я пока для простоты
отбросил. Ограниченную кардинальность номеров серий я тоже пока отбросил. Корреляции между сериями и номерами
в сериях я тоже отбросил. Исхожу из предположения что номер и серия - соврешенно произвольные.

Я решаю (для себя) общую задачу. Исходя из того что обучающая выборка состоит из почти 100 млн ключей
а всего возможно 10 млрд необходимо эти 100 млн как-то хранить и быстро доступаться. При этот ответ на
проверку паспортов из множества

10 млрд - 100 млн = 9 900 000 000

должен быть отрицательный. Тоесть паспорт должен быть действителен для всех тех номеров которые еще не внесены
в обучающую выборку. И в этом есть проблема. ФБ не гарантирует точного ответа. И как захардкодить или как задать
"номера исключения" из этого множества я еще не придумал.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159531
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я про обычное бинарное дерево. Почитал про B+Tree, оптимизировано под страничное хранение, согласен что быстрее.
В моем смешанном способе хранения проблема снимается: если номеров много: биткарта, т.е. 2 чтения. Если мало: максимум 15 чтений, из которых 10 с одной страницы. Хотя и тут можно добавить в начало списка номеров индекс из 32 диапазонов, тогда будет чтение 3х страниц. Подумаю.

Про фильтр Блума: ИМХУ тут он не в тему. Его применение облегчить промахи в выборках, когда сама выборка достаточно тяжелая операция. Тут выборка не тяжелая. Для блума тебе надо какой-то хэш придумать, чтобы равномерно все значения распределил, иначе при 100 млн. бит он просто выродится в биткарту.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159532
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TДля блума тебе надо какой-то хэш придумать, чтобы равномерно все значения распределил, иначе при 100 млн. бит он просто выродится в биткарту.
С этого предложения я не понял. Имплементации которые я брал уже содержат готовый набор API
вместе с хешфункциями и ничего мне придумывать не надо уже.

И почему при 100 млн бит он должен во что-то вырождаться? Я не знаю такого ограничения.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159536
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если битовая карта (та, которая в общепринятом смысле) целиком лежит в ОП,
то плохой номер паспорта определяется мгновенно без обращения к диску
вызовом функции вроде MapTest(Map, Serial, No).
В этом случае на диске карта может храниться как угодно:
или непосредственно, или в виде дельт.

Если в ОП находится только карта серий,
то форматом хранения данных является непосредственно битовая карта.
В этом случае для получения результата необходимо
одно чтение с диска одного байта данных.

Формат данных, предназначенный для передачи, может быть каким угодно.
Удобно передавать ту же карту в сжатом виде из-за небольшого размера (26M).
Если нежелательно использовать архиватор, то подойдет файл с дельтами.
Небольшое изменение формата позволяет уменьшить его размер до 43M.
Как было сказано чуть выше, этот же файл может использоваться
и в работе, если вся битовая карта из него будет грузиться в ОП.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159554
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В моём варианте с com.google.common.hash.BloomFilter и fpp (desired false positive probability) = 0.00001
я получил следующие цифры

Код: plaintext
1.
2.
3.
01/31/2016  05:37 PM       288,700,926 list_of_expired_passports.bloom
01/28/2016  04:53 PM     1,156,615,956 list_of_expired_passports.csv
01/28/2016  04:53 PM       361,240,861 list_of_expired_passports.csv.bz2



Формат карты внутри - достаточно плотен. Вот его шапка (на глаз чтоб оценить энтропию).

Код: sql
1.
2.
3.
4.
5.
00000000: 01 11 02 26 a7 3f 0e a2 - 54 c4 50 e6 3d 93 14 64   ........ T.P....d
00000010: 7f 50 f0 21 de ce ac 86 - 56 a8 a5 bd 53 bd cd 9c   .P...... V...S...
00000020: d8 60 b9 dd 94 9d 65 ae - 43 e1 92 aa a2 d2 42 ca   ......e. C.....B.
00000030: f7 e4 df 56 13 03 62 cc - e5 7b 95 63 7e 6b f6 48   ...V..b. ...c.k.H
....



Как видно... никаких длинных областей нулей и единиц там не прослеживается.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159556
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сжимать ее вобщем-то бесполезно. Практически 7z с дефолтными настройками ничего не может сделать.

Код: sql
1.
2.
01/31/2016  06:22 PM       292,566,109 list_of_expired_passports-bloom.7z
01/31/2016  05:37 PM       288,700,926 list_of_expired_passports.bloom
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159557
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonИ почему при 100 млн бит он должен во что-то вырождаться? Я не знаю такого ограничения.
Извиняюсь. Перепутал, 10 млрд. бит. Биткарта которая покроет все значения.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159558
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TmaytonИ почему при 100 млн бит он должен во что-то вырождаться? Я не знаю такого ограничения.
Извиняюсь. Перепутал, 10 млрд. бит. Биткарта которая покроет все значения.
Простая битовая карта размером в 12 гигабайт? Я-бы такое никому не предложил.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159567
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonDima Tпропущено...

Извиняюсь. Перепутал, 10 млрд. бит. Биткарта которая покроет все значения.
Простая битовая карта размером в 12 гигабайт? Я-бы такое никому не предложил.
1,25 Гб. Всего 4 твоих Блума.

PS Сегодня не я один цифры путаю
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159569
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, а точно.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159575
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T1,25 Гб. Всего 4 твоих Блума.Более того, можно вынести третью и четвертую цифры вперед, добавить кольцевой сдвиг (чтобы счет начинался с нуля). Тогда у битовой карты будет использована только первая четверть, а оставшиеся три четверти можно будет просто обрезать.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159622
__Avenger__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton__Avenger__пропущено...


Прочитай сообщение 18742992 . Все номера паспортов выровнены на границу 4 байта. Серии хранятся в массиве серий от [0..10000].
Спасибо. А сколько времени (мс)у тебя занимает поиск 1 паспорта по этому файлу?

Если мерить GetTickCount-ом, то получается так:
Код: plaintext
1.
2.
3.
4.
5.
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 0 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 15 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 16 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 0 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 16 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 15 Process ExpiredPassportTest.exe (2916)

В среднем 15 ms на паспорт.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159630
__Avenger__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T__Avenger__Мощно, какое-то слишком сложное кодирование исходящего буффера.
Там все элементарно:
допустим S это номер первого байта биткарты в файле, N номер паспорта. Дальше читаем из файла байт (S+N/8) работаем с битом N % 8
чтобы не делать деление и получения остатка (это тяжелые операции) можно их заменить:
деление на 8 - это битовый сдвиг вправо на 3 бита (>> 3)
остаток от деления на 8 - это получение последних трех бит (&7)
Смотря на чем пишешь, на С/С++ можно не менять, компилятор за тебя поменяет.

Для работы с нужным битом:
пусть К номер бита (0-7). Получаем маску M = 1 << K. т.е. битовый сдвиг влево 1 на К разрядов. Математически M = 2^K. Например: при К = 4, M будет 16 или в двоичной 00010000
B - текущее содержимое байта.
Проверка текущего значения бита: (B & M) != 0 (true - установлен)
Установка бита: B = B | M
Сброс бита: B = B & (~M)

&, |, ~ побитовые операции И, ИЛИ, НЕ

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

Спасибо, тут все понятно. Непонятно назначение SavePassportPacket и LoadPassportPacket.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159635
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__Avenger__Непонятно назначение SavePassportPacket и LoadPassportPacket.

Они нужны для сохранения-загрузки всей битовой карты или карты изменений
в формате дельта-кодов. В этом формате значительно экономится место на диске.
Добавил новые версии "2 в 1" процедур SavePassportPacket2 и LoadPassportPacket2,
которые в 2 раза экономнее используют внешнюю память. Удобно для рассылок изменений.

свежий исходник
{$WARN UNSAFE_CODE OFF}
unit ExpiredPassports;

interface

type
TPassportMap= array of array of byte;

procedure MapInvert(var Map: TPassportMap; Serial, No: integer); //инвертировать один бит карты
procedure MapInclude(var Map: TPassportMap; Serial, No: integer); //установить один бит карты
procedure MapExclude(var Map: TPassportMap; Serial, No: integer); //сбросить один бит карты
function MapTest(var Map: TPassportMap; Serial, No: integer): boolean; //получить состояние одного бита карты

procedure LoadPassportList(var Map: TPassportMap; const FileName: string); //загрузить карту, используя файл ФМС

procedure SavePassportMap(var Map: TPassportMap; const FileName: string); //сохранить карту в формате без сжатия
procedure LoadPassportMap(var Map: TPassportMap; const FileName: string); //загрузить карту в формате без сжатия

procedure SavePassportPacket(var Map: TPassportMap; const FileName: string); //сохранить карту в формате дельта-кодов
procedure LoadPassportPacket(var Map: TPassportMap; const FileName: string); //загрузить карту в формате дельта-кодов

procedure SavePassportPacket2(var Map: TPassportMap; const FileName: string); //сохранить карту в формате дельта-кодов 2 в 1
procedure LoadPassportPacket2(var Map: TPassportMap; const FileName: string); //загрузить карту в формате дельта-кодов 2 в 1

implementation

type
TBuffer= array[0..999999] of byte;

procedure MapInvert(var Map: TPassportMap; Serial, No: integer);
begin;
if (Serial<0) or (Serial>9999) or (No<0) or (No>999999) then exit;
if Length(Map)=0 then SetLength(Map, 10000);
if Length(Map[Serial])=0 then begin;
SetLength(Map[Serial], 125000);
FillChar(Map[Serial,0], 125000, 0);
end;
Map[Serial, No shr 3]:=1 shl (No and 7) xor Map[Serial, No shr 3];
end;

procedure MapInclude(var Map: TPassportMap; Serial, No: integer);
begin;
if (Serial<0) or (Serial>9999) or (No<0) or (No>999999) then exit;
if Length(Map)=0 then SetLength(Map, 10000);
if Length(Map[Serial])=0 then begin;
SetLength(Map[Serial], 125000);
FillChar(Map[Serial,0], 125000, 0);
end;
Map[Serial, No shr 3]:=1 shl (No and 7) or Map[Serial, No shr 3];
end;

procedure MapExclude(var Map: TPassportMap; Serial, No: integer);
begin;
if (Serial<0) or (Serial>9999) or (No<0) or (No>999999) then exit;
if Length(Map)=0 then exit;
if Length(Map[Serial])=0 then exit;
Map[Serial, No shr 3]:=(not (1 shl (No and 7))) and Map[Serial, No shr 3];
end;

function MapTest(var Map: TPassportMap; Serial, No: integer): boolean;
begin;
Result:=false;
if (Serial<0) or (Serial>9999) or (No<0) or (No>999999) then exit;
if Length(Map)=0 then exit;
if Length(Map[Serial])=0 then exit;
Result:=1 shl (No and 7) and Map[Serial, No shr 3]<>0;
end;

function SubstrToInt(const s: string; i1, i2: integer): integer;
var
i, c: integer;
begin;
Result:=0;
for i:=i1 to i2 do begin;
c:=ord(s[i])-ord('0');
if cardinal(c)>9 then begin;
Result:=-1;
exit;
end;
Result:=Result*10+c;
end;
end;

procedure LoadPassportList(var Map: TPassportMap; const FileName: string);
var
Fi: Text;
s: string;
begin;
Map:=nil;
Assign(Fi, Filename); Reset(Fi);
while not EOF(Fi) do begin;
ReadLn(Fi, s);
if (Length(s)=11) and (s[5]=',')
then MapInclude(Map, SubstrToInt(s,1,4), SubstrToInt(s,6,11));
end;
CloseFile(Fi);
end;

procedure SavePassportMap(var Map: TPassportMap; const FileName: string);
var
Fi: file;
Serial: integer;
begin;
Assign(Fi, Filename); Rewrite(Fi,1);
for Serial:=0 to Length(Map)-1 do if Length(Map[Serial])=125000 then begin;
BlockWrite(Fi, Serial, 4);
BlockWrite(Fi, Map[Serial,0], 125000);
end;
CloseFile(Fi);
end;

procedure LoadPassportMap(var Map: TPassportMap; const FileName: string);
var
Fi: file;
Serial, Count: integer;
begin;
Map:=nil; SetLength(Map, 10000);
Assign(Fi, Filename); Reset(Fi,1);
while true do begin;
BlockRead(Fi, Serial, 4, Count);
if Count=0 then break;
if (Count<>4) or (Serial<0) or (Serial>9999) then begin;
Map:=nil; break;
end;
SetLength(Map[Serial], 125000);
BlockRead(Fi, Map[Serial,0], 125000, Count);
if Count<>125000 then begin;
Map:=nil; break;
end;
end;
CloseFile(Fi);
end;

procedure EncodeDelta(var Buf: TBuffer; var BufPos: integer; Delta: integer);
begin;
if Delta<=$7F then begin;
Buf[BufPos]:=Delta;
inc(BufPos);
end
else if Delta<=$3FFF then begin;
Buf[BufPos]:=Delta and $3F or $80;
Buf[BufPos+1]:=Delta shr 6;
inc(BufPos, 2);
end
else begin;
Buf[BufPos]:=Delta and $3F or $C0;
Buf[BufPos+1]:=Delta shr 6;
Buf[BufPos+2]:=Delta shr 14;
inc(BufPos, 3);
end;
end;

function DecodeDelta(var Buf: TBuffer; var BufPos: integer): integer;
begin;
Result:=Buf[BufPos];
if Result<=$7F then begin;
inc(BufPos);
end
else if Result<=$BF then begin;
Result:=integer(Buf[BufPos+1]) shl 6
or Result and $3F;
inc(BufPos, 2);
end
else begin;
Result:=integer(Buf[BufPos+2]) shl 14
or integer(Buf[BufPos+1]) shl 6
or Result and $3F;
inc(BufPos, 3);
end;
end;

procedure SavePassportPacket(var Map: TPassportMap; const FileName: string);
var
Fi: file;
Serial, No, OldNo, Val, Bit, BufPos, i, j: integer;
Buf: TBuffer;
begin;
Assign(Fi, Filename); Rewrite(Fi,1);
for Serial:=0 to Length(Map)-1 do if Length(Map[Serial])=125000 then begin;
BlockWrite(Fi, Serial, 4);
Bit:=Map[Serial,0] and 1;
BlockWrite(Fi, Bit, 1);
No:=0; OldNo:=0; BufPos:=0;
for i:=0 to 125000-1 do begin;
Val:=Map[Serial,i];
if (Val=0) and (Bit=0) or (Val=255) and (Bit<>0) then begin;
inc(No, 8);
end
else for j:=0 to 7 do begin;
if Val and 1<>Bit then begin;
EncodeDelta(Buf, BufPos, No-OldNo-1);
OldNo:=No;
Bit:=Bit xor 1;
end;
inc(No);
Val:=Val shr 1;
end
end;
EncodeDelta(Buf, BufPos, No-OldNo-1);
BlockWrite(Fi, BufPos, 4);
BlockWrite(Fi, Buf[0], BufPos);
end;
CloseFile(Fi);
end;

procedure LoadPassportPacket(var Map: TPassportMap; const FileName: string);
var
Fi: file;
Serial, No, OldNo, Bit, BufLen, BufPos: integer;
Buf: TBuffer;
var
Count: integer;
begin;
Map:=nil; SetLength(Map, 10000);
Assign(Fi, Filename); Reset(Fi,1);
while true do begin;
BlockRead(Fi, Serial, 4, Count);
if Count=0 then break;
if (Count<>4) or (Serial<0) or (Serial>9999) then begin;
Map:=nil; break;
end;
Bit:=0; BlockRead(Fi, Bit, 1, Count); Bit:=Bit xor 1;
if (Count<>1) or (Bit and -2<>0) then begin;
Map:=nil; break;
end;
BlockRead(Fi, BufLen, 4, Count);
if (Count<>4) or (BufLen<=0) or (BufLen>SizeOf(Buf)) then begin;
Map:=nil; break;
end;
BlockRead(Fi, Buf[0], BufLen, Count);
if Count<>BufLen then begin;
Map:=nil; break;
end;
SetLength(Map[Serial], 125000);
No:=0; OldNo:=0; BufPos:=0;
while BufPos<BufLen do begin;
No:=DecodeDelta(Buf, BufPos)+1+No;
Bit:=Bit xor 1;
if (BufPos>BufLen) or (No>999999+1) then break;
if Bit=0 then while OldNo<No do begin;
if (OldNo and 7=0) and (OldNo+7<No) then begin;
Map[Serial, OldNo shr 3]:=0;
inc(OldNo, 8);
end
else begin;
Map[Serial, OldNo shr 3]:=(not (1 shl (OldNo and 7))) and Map[Serial, OldNo shr 3];
inc(OldNo);
end;
end
else while OldNo<No do begin;
if (OldNo and 7=0) and (OldNo+7<No) then begin;
Map[Serial,OldNo shr 3]:=$FF;
inc(OldNo, 8);
end
else begin;
Map[Serial, OldNo shr 3]:=1 shl (OldNo and 7) or Map[Serial, OldNo shr 3];
inc(OldNo);
end;
end;
end;
if (BufPos<>BufLen) or (No<>999999+1) then begin;
Map:=nil; break;
end;
end;
CloseFile(Fi);
end;

procedure EncodeDelta2(var Buf: TBuffer; var BufPos, CodeLen: integer; Delta: integer);
begin;
if (CodeLen>0) and (Delta<=8) then begin; //пробуем запихнуть маленькую дельту в предыдущий код
if Delta=0 then begin; //используем $40 как флаг нулевой дельты
if CodeLen=1
then Buf[BufPos-1]:=$40 or Buf[BufPos-1]
else Buf[BufPos+1-CodeLen]:=$40 or Buf[BufPos+1-CodeLen];
CodeLen:=0; //чтобы больше не пихать, место занято
exit;
end
else if (CodeLen=1) and (Buf[BufPos-1]<=7) then begin; //если предыдущий код был маленький, то пихаем в него ненулевую дельту
Buf[BufPos-1]:=(Delta-1) shl 3 or $80 or Buf[BufPos-1];
CodeLen:=0; //чтобы больше не пихать, место занято
exit;
end;
end;
if Delta<=$3F then begin;
Buf[BufPos]:=Delta;
inc(BufPos);
CodeLen:=1;
end
else if Delta<=$FFF then begin;
Buf[BufPos]:=Delta and $3F or $C0;
Buf[BufPos+1]:=Delta shr 6;
inc(BufPos, 2);
CodeLen:=2;
end
else begin;
Buf[BufPos]:=Delta and $3F or $C0;
Buf[BufPos+1]:=Delta shr 6 and $3F or $80;
Buf[BufPos+2]:=Delta shr 12;
inc(BufPos, 3);
CodeLen:=3;
end;
end;

function DecodeDelta2(var Buf: TBuffer; var BufPos, NextDelta: integer): integer;
begin;
if NextDelta>=0 then begin;
Result:=NextDelta;
NextDelta:=-1;
exit;
end;
Result:=Buf[BufPos];
if Result<=$3F then begin;
inc(BufPos);
end
else if Result<=$7F then begin;
NextDelta:=0;
Result:=Result and $3F;
inc(BufPos);
end
else if Result<=$BF then begin;
NextDelta:=Result shr 3 and $7 + 1;
Result:=Result and 7;
inc(BufPos);
end
else begin;
if Buf[BufPos+1] and $40<>0 then NextDelta:=0;
Result:=integer(Buf[BufPos+1]) and $3F shl 6
or Result and $3F;
if Buf[BufPos+1] and $80=0
then inc(BufPos, 2)
else begin;
Result:=integer(Buf[BufPos+2]) shl 12 or Result;
inc(BufPos, 3);
end;
end;
end;

procedure SavePassportPacket2(var Map: TPassportMap; const FileName: string);
var
Fi: file;
Serial, No, OldNo, Val, Bit, BufPos, CodeLen, i, j: integer;
Buf: TBuffer;
begin;
Assign(Fi, Filename); Rewrite(Fi,1);
for Serial:=0 to Length(Map)-1 do if Length(Map[Serial])=125000 then begin;
BlockWrite(Fi, Serial, 4);
Bit:=Map[Serial,0] and 1;
BlockWrite(Fi, Bit, 1);
No:=0; OldNo:=0; BufPos:=0; CodeLen:=0;
for i:=0 to 125000-1 do begin;
Val:=Map[Serial,i];
if (Val=0) and (Bit=0) or (Val=255) and (Bit<>0) then begin;
inc(No, 8);
end
else for j:=0 to 7 do begin;
if Val and 1<>Bit then begin;
EncodeDelta2(Buf, BufPos, CodeLen, No-OldNo-1);
OldNo:=No;
Bit:=Bit xor 1;
end;
inc(No);
Val:=Val shr 1;
end
end;
EncodeDelta2(Buf, BufPos, CodeLen, No-OldNo-1);
BlockWrite(Fi, BufPos, 4);
BlockWrite(Fi, Buf[0], BufPos);
end;
CloseFile(Fi);
end;

procedure LoadPassportPacket2(var Map: TPassportMap; const FileName: string);
var
Fi: file;
Serial, No, OldNo, Bit, BufLen, BufPos, NextDelta: integer;
Buf: TBuffer;
var
Count: integer;
begin;
Map:=nil; SetLength(Map, 10000);
Assign(Fi, Filename); Reset(Fi,1);
while true do begin;
BlockRead(Fi, Serial, 4, Count);
if Count=0 then break;
if (Count<>4) or (Serial<0) or (Serial>9999) then begin;
Map:=nil; break;
end;
Bit:=0; BlockRead(Fi, Bit, 1, Count); Bit:=Bit xor 1;
if (Count<>1) or (Bit and -2<>0) then begin;
Map:=nil; break;
end;
BlockRead(Fi, BufLen, 4, Count);
if (Count<>4) or (BufLen<=0) or (BufLen>SizeOf(Buf)) then begin;
Map:=nil; break;
end;
BlockRead(Fi, Buf[0], BufLen, Count);
if Count<>BufLen then begin;
Map:=nil; break;
end;
SetLength(Map[Serial], 125000);
No:=0; OldNo:=0; BufPos:=0; NextDelta:=-1;
while (BufPos<BufLen) or (NextDelta>=0) do begin;
No:=DecodeDelta2(Buf, BufPos, NextDelta)+1+No;
Bit:=Bit xor 1;
if (BufPos>BufLen) or (No>999999+1) then break;
if Bit=0 then while OldNo<No do begin;
if (OldNo and 7=0) and (OldNo+7<No) then begin;
Map[Serial, OldNo shr 3]:=0;
inc(OldNo, 8);
end
else begin;
Map[Serial, OldNo shr 3]:=(not (1 shl (OldNo and 7))) and Map[Serial, OldNo shr 3];
inc(OldNo);
end;
end
else while OldNo<No do begin;
if (OldNo and 7=0) and (OldNo+7<No) then begin;
Map[Serial,OldNo shr 3]:=$FF;
inc(OldNo, 8);
end
else begin;
Map[Serial, OldNo shr 3]:=1 shl (OldNo and 7) or Map[Serial, OldNo shr 3];
inc(OldNo);
end;
end;
end;
if (BufPos<>BufLen) or (NextDelta>=0) or (No<>999999+1) then begin;
Map:=nil; break;
end;
end;
CloseFile(Fi);
end;

end.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159636
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

эх, жаль, забыл исходнику тег добавить.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159664
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonДавайте отложим в сторону юридические моменты. Это не интересно для sql.ru.

Лучше обсужить способы storage и оперативный доступ.
программирование несколько, шире чем кодирование
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159671
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
__Avenger__Если мерить GetTickCount-ом, то получается так:
Код: plaintext
1.
2.
3.
4.
5.
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 0 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 15 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 16 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 0 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 16 Process ExpiredPassportTest.exe (2916)
Debug Output: TFastDBFinder(0000000001D4ED50).IsFound = 15 Process ExpiredPassportTest.exe (2916)

В среднем 15 ms на паспорт.
Тут что-то неправильно мерялось. Откуда эти нули?
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159673
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftDima T1,25 Гб. Всего 4 твоих Блума.Более того, можно вынести третью и четвертую цифры вперед, добавить кольцевой сдвиг (чтобы счет начинался с нуля). Тогда у битовой карты будет использована только первая четверть, а оставшиеся три четверти можно будет просто обрезать.
У меня была мысль оценить распределение паспортных пространств во всём универсуме.
Для этого визуализировать диапазоны и серии на картинке в виде полосок.
Как я это планировал сделать. Например - представить номер паспорта в формате
AAAA,BBBBBB как точку с координатами (AAAAB,BBBBB)
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159680
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

Да тут особо нечего оценивать. Неравномерностей я вижу всего две:
- 3 и 4 цифры, т.к. система работает порядка 25 лет.
- старшие цифры номера, т.к. далеко не каждый регион израсходовал весь диапазон номеров в конкретный год. (Кстати, это входит в этот файл или нет?)
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159699
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вобщем как-то вот так. Белым пикселам соответствуют использованные
паспортнные номера из нашего списка.

Грубо 0000,000000 должен соотвествовать пикселу с координатами (0,0).
Правому нижнему - 9999,999999 - (511,511).

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

Если я где-то ошибся то прошу меня поправить.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159707
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1) Немножко переделал.

0000,000000 должен соотвествовать пикселу с координатами (0,0).

Да. Координаты - наоборот. Строкам соотвествуют серии. Столбцам - номера.

Так более правильно.

2) В картинке появились полу-тона. Просто рендерю в 1024х1024 а потом уменьшаю в два раза чтоб в форуме значить как-то
красивее смотрелось.
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159708
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

А если 3 и 4 цифры серии вынести вперед, то какая картина получится?
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39159710
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftmayton,

А если 3 и 4 цифры серии вынести вперед, то какая картина получится?
Завтра, бро. Меня одолевает древне-греческий бог Гипнос.
Осоловело тру глазищи...
...
Рейтинг: 0 / 0
Два число в одно и обратно
    #39160077
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Одолел божество. Проснулся.
...
Рейтинг: 0 / 0
25 сообщений из 209, страница 8 из 9
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Два число в одно и обратно
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]