Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Число, соответствующее буквенному названию колонки, нужны функции 
:(
    Опции темы
motorway
  Дата 21.7.2009, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 578
Регистрация: 2.3.2008

Репутация: 1
Всего: 0



Нужны две функции.

1) По буквенному названию, аналогичному названиям колонок в Экселе (A, B, ... AB, CDD), получает соотв. число по порядку.

Пример:
А -> 1
B -> 2
Z -> 26
AA -> 27
AF -> 32
...

2) По такому номеру получает буквенный вид колонки

1 -> A
2 -> B
26 -> Z
27 -> AA
53 -> BA
...
PM MAIL   Вверх
enof
Дата 21.7.2009, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 837
Регистрация: 23.1.2009
Где: Санкт-Петербург

Репутация: 30
Всего: 35



Над этой темой уже думал в соседней теме, да было лень код дописать, там пару проблем было. smile 
вот часть по преобразованию в число:
Код

$abc = array(); //Массив-алфавит
for($a = 'A', $i = 1; $a < 'Z'; $i++, $a++)
{
    $abc[$a] = $i;
}
$abc['Z'] = 26;
$arr_sym = array("A", "F");//массив из букв координаты ячейки;
$result = 0;
$result += $abc[array_pop($arr_sym)];
for($i = count($arr_sym); $i > 0; $i--)
{
    $result += $abc[$arr_sym[$i-1]] * 26;
}
echo $result;

Если нужно, могу выложить код полностью, с преобразованием текста из соседней темы, но только позднее, щас тороплюсь.
PM MAIL ICQ Skype   Вверх
motorway
Дата 21.7.2009, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 578
Регистрация: 2.3.2008

Репутация: 1
Всего: 0



Мне трехзначные названия тоже нужны smile
PM MAIL   Вверх
motorway
Дата 21.7.2009, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 578
Регистрация: 2.3.2008

Репутация: 1
Всего: 0



В общем, что-то этот код мне не очень понравился, я решил сделать более элегантный. Вот что получилось:

Функция возвращает номер для колонки
Код

function colnum ($str)
{
if (strlen($str)==1)
$num=ord($str)-64;
if (strlen($str)==2)
$num=26*(ord($str{0})-64)+ord($str{1})-64;
if (strlen($str)==3)
$num=676*(ord($str{0})-64)+26*(ord($str{1})-64)+ord($str{2})-64;

return $num;
};


PM MAIL   Вверх
enof
Дата 21.7.2009, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 837
Регистрация: 23.1.2009
Где: Санкт-Петербург

Репутация: 30
Всего: 35



Цитата(motorway @  21.7.2009,  20:04 Найти цитируемый пост)
Мне трехзначные названия тоже нужны smile 

да хоть двадцати, мой код не зависит от количества букв. Вычисление числа через массив действительно криво.
PM MAIL ICQ Skype   Вверх
motorway
Дата 21.7.2009, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 578
Регистрация: 2.3.2008

Репутация: 1
Всего: 0



А вот и вторая:

Код

function numcol ($str)
{
if ($str<=26)
$col=chr(64+$str);
if ($str>26 and $str<=702)
$col=chr(floor(($str-1)/26)+64).chr($str-26*floor(($str-1)/26)+64);
if ($str>702 and $str<=16384)
{
$col=chr(floor(($str-27)/676)+64);
$str=$str-676*(ord($col)-64);
$col.=chr(floor(($str-1)/26)+64).chr($str-26*floor(($str-1)/26)+64);
};
return $col;
};


Кому нужно, питайтесь  smile 
PM MAIL   Вверх
NLspieler
Дата 21.7.2009, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 619
Регистрация: 13.10.2008
Где: Берлин

Репутация: 16
Всего: 19



Придумал функцию преобразующую буквы в числа, обратную функцию пока не осилил.

Код

<?

/////////////////
$alphavit = 'A B C D E F G H I J K L M N O P Q R S T U V W X Y Z' ; //Алфавит 26 букв
$alphavit = explode (' ' , $alphavit) ; //Массив с символами
////////////////

function symbol_to_num ($symbol) //Преобразует !один! символ в число
{
    global $alphavit ;
    $flip = array_flip ( $alphavit ) ; //Поменять местами ключи и значения
    return $flip[$symbol] + 1 ;
}

function string_to_num ($string) //Преобразует АА в 27
{
    $strlen = strlen ($string) ;
    $return = 0 ;
    for ($n = 0 ; $n < $strlen ; $n++)
    {
        $key = $strlen - 1 - $n ;
        $return += symbol_to_num ( $string[$key] ) * pow (26 , $n) ;
    }
    return $return ;
}

echo string_to_num ('ABZTH')  ;
?>



Это сообщение отредактировал(а) NLspieler - 21.7.2009, 22:22
PM MAIL   Вверх
NLspieler
Дата 21.7.2009, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 619
Регистрация: 13.10.2008
Где: Берлин

Репутация: 16
Всего: 19



Осилил функцию обратного преобразования из числа в буквенную комбинацию

Код

/////////////////
$alphavit = 'A B C D E F G H I J K L M N O P Q R S T U V W X Y Z' ; //Алфавит 26 букв
$alphavit = explode (' ' , $alphavit) ; //Массив с символами
////////////////

function num_to_symbol ($num) //Преобразует число от 1 до 26 в соответствующий символ
{
    global $alphavit ;
    $key = $num - 1 ;
    return $alphavit[$key] ;
}

function num_to_string ($num) //53 -> BA
{
    $num = $num + 0 ;
    if ($num < 1) die ('Недопустимый аргумент функции num_to_string ($num)') ;
    if ($num == 1) return 'A' ;
    $log = log10 ($num) / log10 (26) ; //Логарифм числа по основанию 26
    $razryady = ceil ($log) ;
    $return = '' ;
    for ($n = $razryady - 1 ; $n >= 0 ; $n--)
    {
        $pow = pow (26 , $n) ;
        $y = floor ($num / $pow) ;
        $return .= num_to_symbol ($y) ;
        $num -= $y * $pow ;
    }
    return $return ;
}

PM MAIL   Вверх
ksnk
Дата 21.7.2009, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Хм... а про base_convert вроде как никто и не слышал?

Код

function dec2let($number){
   return strtr(base_convert($number, 10, 26),'0123456789abcdefghijklmnop','ABCDEFJHIJKLMNOPQRSTUVWXYZ');
}
function let2dec($number){
   return base_convert(strtr($number,'ABCDEFJHIJKLMNOPQRSTUVWXYZ','0123456789abcdefghijklmnop'), 26, 10);
}




--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
NLspieler
Дата 21.7.2009, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 619
Регистрация: 13.10.2008
Где: Берлин

Репутация: 16
Всего: 19



Цитата(ksnk @ 21.7.2009,  22:12)
Хм... а про base_convert вроде как никто и не слышал?

Проблема в том, что тут нет цифры ноль, поэтому речь уже не идет о числах 26 степени.
PM MAIL   Вверх
ksnk
Дата 21.7.2009, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Цитата(NLspieler @  21.7.2009,  22:16 Найти цитируемый пост)
тут нет цифры ноль

А чем буква A не цифра 0?  smile 


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
NLspieler
Дата 21.7.2009, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 619
Регистрация: 13.10.2008
Где: Берлин

Репутация: 16
Всего: 19



Цитата(ksnk @  21.7.2009,  22:20 Найти цитируемый пост)
А чем буква A не цифра 0?   

A - это 1
Z - это 26
AA -  это 27

Как итог, функции работают не корректно
PM MAIL   Вверх
ksnk
Дата 25.7.2009, 20:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Вот, блин! smile 
И кто такой формат придумал? Lotus или Билли?
Код

function dec2let($number,$back=''){
    static $dig='0123456789abcdefghijklmnop';
    static $let='ABCDEFJHIJKLMNOPQRSTUVWXYZ';
    if(!$back) {
        $x=base_convert($number-1, 10, 26);
        if ($number>26)
            $x{0}=strtr($x{0},$dig.'_','_'.$dig);
        return strtr($x,$dig,$let);
    } else {
        if(strlen($number)>1) 
            $number{0}=strtr($number{0},'_'.$let,$let.'_');
        return base_convert(strtr($number,$let,$dig), 26, 10)+1;
    }
}

for($i=1;$i<60; $i++)
    echo $i.'='.base_convert($i, 10, 26).'--'.dec2let($i).'='. dec2let(dec2let($i),'back').'<br>';


Это сообщение отредактировал(а) ksnk - 25.7.2009, 20:44


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Mal Hack
Дата 25.7.2009, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 122
Всего: 261



Предложу, пожалуй, несколько более отимальный вариант:
Код

$len = strlen($str);

$num = ord($str) - 64;

if($len > 1)
{ $num = $num * 26 + ord($str[1]) - 64; }

if($len == 3)
{ $num = $num * 26 + ord($str[2]) - 64; }

Мог несколько наврать с математикой - ошибка на единицу ("следующий +1, предыдущий"), но подход вроде верен. Про ord() - 64 взял у кого-то с этого топика, не проверяя.

Что касается обратного преобразования (проверить не могу, но вроде бы так):
Код

$num1 = floor($num / 676);
$str = $str . chr($num1 + 64);
$num2 = floor(( $num - $num1 * 676 ) / 26);
$str = $str . chr($num2 + 64);
$num3 = ( $num - $num1 * 676 - $num2 * 26 );
$str = $str . chr($num3 + 64);


Как видно, принцип прост и сводится к основным математическим операциям.
PM ICQ   Вверх
Photon
Дата 26.7.2009, 01:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Злобный программер
**


Профиль
Группа: Участник
Сообщений: 282
Регистрация: 27.2.2009
Где: Таганрог

Репутация: 10
Всего: 12



Код

    function char_to_num($char) {
     return ord($char) - 64;
    }
    function num_to_char($num) {
     return (chr($num + 64));
    }
    function num_to_string($num) {
        $log = log10 ($num) / log10 (26);
        $razryady = ceil($log);
        $return = '';
        for ($n = $razryady - 1; $n >= 0; $n--) {
            $pow = pow(26, $n);
            $y = floor($num / $pow);     
            if ($y * $pow == $num && $num - $y * $pow != 0) {
                $res .= num_to_char($y - 1);
                $y--;
            }
            else
                $res .= num_to_char($y);
            $num -= $y * $pow - 1;
        }                
        return $res;
    }
    function string_to_num($str, $index = 0) {
     if ($index < strlen($str)){
         $cnt = strlen($str) - 1;
         return pow(26,($cnt - $index))*char_to_num($str[$index]) + string_to_num($str, $index+1);       
        }
        else
            return 0;
    }                         


В-общем как-то так.. smile


--------------------
With best regards..
PM MAIL ICQ Skype GTalk Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0667 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.