Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Бинарные числа на PHP
 
 автор: Eugene77   (26.05.2007 в 16:47)   письмо автору
 
 

Я хочу сохранять в базе информацию о посещении каждым из пользователей каждой из страниц. Но страниц в перспективе намечается сделать довольно много (200). Получается большой объём. Как минимизировать? У меня идея такая:
У каждой страницы есть порядковый номер, а в таблице зарегистрированных пользователей есть бинарная колонка, где для каждого есть ряд из 200 нуликов и единичек: 0001001000010001, где нулик обозначает непосещённые страницы, а единица - посещённые.
При посещении страницы это бинарное число соответствующим образом маскируется преобразуется в интеджер и заново сохраняется в ячейку.
Но не знаю как даже подступиться к этому потому что
1) Нигде не найду как PHP работает с бинарными числами
2)Лон интеджер всё же маловат для моих запросов. Тогда какое поле отводить в базе?
Есть идеи?

   
 
 автор: kasmanaft   (26.05.2007 в 17:30)   письмо автору
 
   для: Eugene77   (26.05.2007 в 16:47)
 

-

   
 
 автор: bronenos   (26.05.2007 в 17:30)   письмо автору
 
   для: Eugene77   (26.05.2007 в 16:47)
 

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

   
 
 автор: Eugene77   (26.05.2007 в 20:40)   письмо автору
 
   для: bronenos   (26.05.2007 в 17:30)
 

Спасибо, действительно, удобней будет работать с массивом .
Только вот
занести в сериализованном виде - тут у меня какой-то пробел в знаниях.
Можно кусочек кода написать для ясности?

   
 
 автор: kasmanaft   (26.05.2007 в 20:55)   письмо автору
 
   для: Eugene77   (26.05.2007 в 20:40)
 

Я думал Вы хотите числа хранить - память эконимите или еще чего извращенное.. А тут на массив согласились.
Почему бы эти нули и единички не сохранить строкой?


// это то, что получится с массивом
<?php
for ($i 0$i 200$i++, $arr[$i] = 1);
echo 
serialize($arr);
?>

   
 
 автор: Eugene77   (27.05.2007 в 20:01)   письмо автору
 
   для: kasmanaft   (26.05.2007 в 20:55)
 

Спасибо, что пролили свет на мою тёмную голову. Теперь я понял что bronenous имеет ввиду, но согласиться не могу. Огромная таблица получится. Не реально это лучше даже не начинать!
Подскажите лучше как грамотно и аккуратно сделать, минимум места заняв.
Некое подобие бинарного поля надо изобрести в таблице. Это будет реальный предел экономии места. Он не раздует мне таблицу больше разумных пределов.

   
 
 автор: Trianon   (26.05.2007 в 22:16)   письмо автору
 
   для: Eugene77   (26.05.2007 в 16:47)
 

Наверняка SET либо (если SET маловат ) BLOB.
Если BLOB - в php будете работать с ним, как с обычной строкой. Каждый символ - восемь элементов множества.

   
 
 автор: bronenos   (26.05.2007 в 22:20)   письмо автору
 
   для: Trianon   (26.05.2007 в 22:16)
 

serialize ($massiv)
вот то что вернет эта функция запишите в таблице
когда будете читать массив получите так
unserialize ($zapis)

   
 
 автор: Trianon   (26.05.2007 в 22:22)   письмо автору
 
   для: bronenos   (26.05.2007 в 22:20)
 

Не надо мне на вопрос отвечать - тем более - неправильно. Я умею с битовыми картами работать.

   
 
 автор: bronenos   (28.05.2007 в 22:18)   письмо автору
 
   для: Trianon   (26.05.2007 в 22:22)
 

Да при чем тут.....

   
 
 автор: Eugene77   (27.05.2007 в 20:18)   письмо автору
 
   для: Trianon   (26.05.2007 в 22:16)
 

Это мне каждый символ отдельно маскировать придётся?
Э-хе-хе - трудна работа програмиста!
Хотя, может так даже удобнее - масок всего восемь.
Только я не хочу BLOB использовать. Я хотел сделать всего два столбца, фиксированной ширины к тому же, чтобы максимально быстро работало.
Или что, у меня выбора нет?

   
 
 автор: Trianon   (28.05.2007 в 00:10)   письмо автору
 
   для: Eugene77   (27.05.2007 в 20:18)
 

никто не мешает зафиксировать ширину у этого столбца.
Если не хотите понапрасну расходовать память и усложнять скрипт лишними перекодировками - альтернативы нету.

Вот алгоритмическая конструкция, проверяющая, поднят ли флаг в множестве:
function check_element($str, $elem, $on)
{
$idx = $elem >>3; $mask = 1<<($elem&7);
return (ord($str[$idx]) & $mask) != 0;
}
Конструкция, присваивающая элемент, пишется аналогично.

   
 
 автор: Eugene77   (28.05.2007 в 22:07)   письмо автору
 
   для: Trianon   (28.05.2007 в 00:10)
 

Спасибо!
Как же всё-таки написать обратную функцию?
Так?

function set_element($str, $elem)
{
$idx = $elem >>3; $mask = 1<<($elem%7);
return substr($str,0,$idx-1).chr(ord($str[$idx]) | $mask).substr($str,$idx+1);
}

Если так, то мне надо начинать нумерацию страниц сайта с 1.
Это возможно? Или autoincriment с нуля начнёт?

   
 
 автор: Trianon   (28.05.2007 в 23:45)   письмо автору
 
   для: Eugene77   (28.05.2007 в 22:07)
 

autoincrement начинает с единицы.
Да. примерно так.Только почему $idx-1 ?

   
 
 автор: Eugene77   (29.05.2007 в 19:42)   письмо автору
 
   для: Trianon   (28.05.2007 в 23:45)
 

Только почему $idx-1 ?
Ничего умного тут сказать не могу. У меня вообще понятия о PHP пока довольно туманные.
Я не знаю включительно функция возвращает подстроку или исключительно.
Да и оператор >> меня в шок поверг - его в справочнике нет. Что, на самом деле он есть? Может у меня справочник устаревший? Потом сдвиги вообще-то разные бывают, циклические, например. Как я могу быть уверен, что это тот, что надо? В смысле, я доверяю, конечно, но твёрдой почвы под ногами пока почувствовать не могу. То есть сама ситуация подразумевает отсутствие этой почвы у меня.
Потом, строковые функции будут ли работать с несимвольными величинами?
Скажите да!
А то у меня слишком много сомнений для такого маленького отрывка кода, который сам по-себе ещё и не испытаешь. Придётся довольно большой фрагмент сразу сочинять. А я пока легко спотыкаюсь на самом элементарном.

   
 
 автор: Trianon   (29.05.2007 в 20:05)   письмо автору
 
   для: Eugene77   (29.05.2007 в 19:42)
 

>Ничего умного тут сказать не могу. У меня вообще понятия о PHP пока довольно туманные.
>Я не знаю включительно функция возвращает подстроку или исключительно.

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

>Да и оператор >> меня в шок поверг - его в справочнике нет.

В мануале есть.

>Потом сдвиги вообще-то разные бывают, циклические, например

Циклические сдвиги не реализованы встроенными в язык операциями ни на одном из диалектов C, насколько мне известно, и в других языках тоже. Хотя со сдвигами и без того неоднозначностей хватает.

>Как я могу быть уверен, что это тот, что надо?

Вот этот раздел руководства прояснит Вам картину:
http://ru2.php.net/manual/ru/language.operators.bitwise.php

>Потом, строковые функции будут ли работать с несимвольными величинами?
>Скажите да!

С байтовыми цепочками произвольного вида? Безусловно.

   
 
 автор: Eugene77   (29.05.2007 в 21:51)   письмо автору
 
   для: Trianon   (29.05.2007 в 20:05)
 

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

При таком хорошем освещении, сразу заметно, что единицу я зря отнимаю.
Так у меня при каждом обращении один байт будет теряться. Исправлю. Спасибо!
Остальное тоже полезно.

Теперь вот не знаю как поле blob инициализировать.
Вот отрывок из файла:


<?
$qwiery
[] = "CREATE TABLE visitors(
id int(6) NOT NULL auto_increment,
pages blob NOT NULL default '??????????',
PRIMARY KEY (id)
)TIPE = MyISAM"
;

$create_table true;
foreach(
$qwiery as $value){
    if(!
mysql_query($value)) $create_table false;
}
?>


Кстати, жаль, что циклические сдвиги недоступны, я бы на них щифрование сделал - проще не придумаешь!

   
 
 автор: Trianon   (29.05.2007 в 22:29)   письмо автору
 
   для: Eugene77   (29.05.2007 в 21:51)
 

запишите там сразу нужное количество нулевых байт:
<?
$query
[] = "CREATE TABLE visitors( 
id int(6) NOT NULL auto_increment, 
pages blob NOT NULL default '"
.  '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' ."', 
PRIMARY KEY (id) 
)"




Циклические сдвиги можно вычислить, как комбинацию логических, соединенных по побитовому ИЛИ.

А шифрование лучше самому не писать, а применять уже готовое. Уж больно скользкая область. Тем более что симметричных шифров в php реализовано вагон, а для асимметричных никакие циклические сдвиги не нужны.

   
 
 автор: Unkind   (29.05.2007 в 22:31)   письмо автору
 
   для: Trianon   (29.05.2007 в 22:29)
 

TYPE = MyISAM

   
 
 автор: Trianon   (29.05.2007 в 22:34)   письмо автору
 
   для: Unkind   (29.05.2007 в 22:31)
 

Угу. Поправил :)

   
 
 автор: Eugene77   (30.05.2007 в 10:58)   письмо автору
 
   для: Trianon   (29.05.2007 в 22:29)
 

Спасибо!
А есть симметричное шифрование, которое длину строки не меняет?

   
 
 автор: Trianon   (30.05.2007 в 17:41)   письмо автору
 
   для: Eugene77   (30.05.2007 в 10:58)
 

если правильно применять шифрующий движок, то есть использовать не simple permutations а хотя бы в cipher feedback режиме, до длина строки не меняется.

   
 
 автор: Eugene77   (30.05.2007 в 21:40)   письмо автору
 
   для: Trianon   (29.05.2007 в 22:29)
 

Если соединить всё это вместе, то у меня получается вот такой код на три файла.
Я его привожу весь, потому что, как мне кажется, выходит довольно полезная утилита, позволяющая любому посетителю в любой момент времени узнать какие странички он ещё не видел. Я бы не отказался от такой возможности даже на этом сайте «софттайма», не говоря уже о некоторых других, в которых явно не хватает этой утилиты.
Конечно сейчас в тексте программы море ошибок, но иначе и не может быть – это ведь моя первая программа на PHP, которую я собираюсь реально использовать.
Заранее благодарю всех, кто укажет на ошибки и подскажет возможные усовершенствования. Особое спасибо Трианону! Без него я не сумел бы даже подступиться к этой задаче!
Файл вывода на экран списка посещённых страниц пока не рассматривается.
Извините за комментарии на английском языке. Мой Dreamweaver с русским вытворяет что попало. Может мне на другой редактор пересесть?

В начале создаются две таблицы каждая из двух колонок. Одна содержит названия файлов, вторая id посетителей и специальное поле типа blob, в котором каждый бит отвечает за посещение страницы с соответствующим номером. Id посетителей хранятся в cookies.


<?php
//  This file create tables to count visits of eatch visitor of eatch page
$qwiery[] = "CREATE TABLE visitors(
id int(6) NOT NULL auto_increment,
pages blob NOT NULL default '"
.  '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' ."',
PRIMARY KEY (id)
)TYPE = MyISAM"
;

$qwiery[] = "CREATE TABLE pages(
id int(6) NOT NULL auto_increment,
page tinytext NOT NULL default '',
PRIMARY KEY (id)
)TYPE = MyISAM"
;


require_once(
"connect_db.inc");
$create_table true;
foreach(
$qwiery as $value){
    if(!
mysql_query($value)) $create_table false;
}
if (
$create_table) echo "??????? ??????? ???????";
    else echo 
"?????? ??? ???????? ??????";
?>


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


<?php
// This part of code must be included in every file
require_once("connect_db.inc");
$query="SELECT count(*) FROM visitors";  // Count number of visitors
$vstrs mysql_query($query);
$v mysql_fetch_array($vstrsMYSQL_NUM);
if(!isset(
$COOKIE['id'] || $COOKIE['id']>$v) {  // Id of visitor supposed to be in cookies
        
$id $v+1;
        
setcookie("id"$idtime()+60*24*60*60); // Set cookie on two monthes period
        
header("Location: cookies_on.php?id=$id");  // Check if cookie really set 
}
        else 
$id $COOKIE['id'];
        
if(isset(
$PHP_SELF$name_page=$PHP_SELF// Take name of current page
    
else $name_page='no_page';
$query="SELECT id FROM pages WHERE $page = $name_page";  // Find out id number of page
$id_page mysql_query($query);
if(!
$id_page || mysql_num_rows($id_page)<1)) { // If page not registered in the table, we are to add record into the table pages
    
$query="INSERT INTO pages page=$name_page";      // Insert new line into table pages
    
if(!mysql_query($query)) echo "New page $name_page not inserted";
    
$query="SELECT id FROM pages WHERE page = $name_page";  // Find out id number of page
    
if(!($id_page mysql_query($query))) echo "New line is not created";
}

$pg mysql_fetch_array($id_pageMYSQL_NUM);
$query="SELECT pages FROM visitors WHERE id = $id";  // Extract list of visited pages
$p mysql_query($query);   //  
$pages mysql_result($p1);
$p=set_element($pages$pg);    // Add current page to list of visited pages
$query="UPDATE visitors pages=$pages WHERE id = $id";
mysql_query($query);   //  


function set_element($str$elem){
for(
$i=$elem-strlen($str); $i<0$i++) $str ='/0'.$str;  // In case if number of pages exeed initialy reserved place in colomn pages, we make the col. wider
$idx $elem >>3$mask 1<<($elem%7);
return 
substr($str,0,$idx).chr(ord($str[$idx]) | $mask).substr($str,$idx+1);
}

function 
check_element($str$elem){
$idx $elem >>3$mask 1<<($elem%7);
return (
ord($str[$idx]) & $mask) != 0;
}
?>


Этот маленький файл проверяет, действительно ли cookie установлен.


<?php
// file:  cookies_on.php
if(!isset($_GET['id']) die("Name of cookie not set");
if(!isset(
$_COOKIE['id']) die("Please, let us to set cookie!");
if(
$_GET['id'] != $_COOKIE['id']) die("Wrong cookie value");
header("Location: $_SERVER['HTTP_REFERER']");
?>

   
 
 автор: Eugene77   (30.05.2007 в 21:47)   письмо автору
 
   для: Trianon   (29.05.2007 в 22:29)
 

----

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования