Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как определить, является ли строка числом? нигде не могу найти... 
:(
    Опции темы
HalkaR
Дата 17.6.2004, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пуфыстый назгул
****


Профиль
Группа: Экс. модератор
Сообщений: 2132
Регистрация: 8.12.2002
Где: В Москве

Репутация: нет
Всего: 42



MuToGeN , нету.

В Перле вообще нет разницы между строкой и числом. Если ты сравниваешь пременные eq, то они сравниваются как строки, если ==, то как числа.
PM MAIL   Вверх
pompei
Дата 6.12.2007, 07:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

Репутация: 2
Всего: 6



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

Люди! Давайте всё таки разберёмся, как это сделать!!!!!!!!!!!!

Информация для размышления:

В перле есть возможность отличить строку от числа. Посмотрите вывод программы:
Код

use Data::Dumper;
print Dumper 1;
print Dumper "1";

Вывод такой:
Код

$VAR1 = 1;
$VAR1 = '1';

От сюда сразу напрашивается решение сделать что-то типа этого:
Код

use Data::Dumper;
sub isNumber {
  my $x = shift;
  my $y = Dumper( $x );
  return $y !~ /'/; #'если есть апостроф, то у нас строка
}

print isNumber( 1 ) ? "число\n" : "строка\n";
print isNumber( "1" ) ? "число\n" : "строка\n";

Вывод такой:
Код

число
строка

Но это очень уродливый пирожёк.
Проследить как работает функция Dumper не получается, извилин не хватает. Может у кого получиться?

Люди давайте разберёмся, а!!!


Это сообщение отредактировал(а) pompei - 6.12.2007, 07:22
--------------------
А всё оказывается гораздо проще: пассивные наноструктуры - активные наноструктуры - системы наносистем - молекулярные наносистемы - сингулярность! По пять лет на каждый этап.
PM MAIL   Вверх
Ramirez
Дата 6.12.2007, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 305
Регистрация: 18.1.2005
Где: Moscow, ExUSSR

Репутация: 4
Всего: 5



Собственно, сам data dumper определяет следующим образом:

Код

$val =~ /^(?:0|-?[1-9]\d{0,8})\z/ # safe decimal number


или вот еще вариант:

Код

# regular expression matching a plain number
$RE_NUMBER = qr/
    (?<!\w)                         # start of a number, not the continuation of an identifier like 'cap12'
    [+-]?                           # optional sign
    (?:(?:\d+(?:\.\d*)?)|(?:\.\d+)) # mantissa
    (?:e[+-]?\d+)?                  # optional exponent
    /ix;


интересно было-бы увидеть надежный способ без регекспов.

Это сообщение отредактировал(а) Ramirez - 6.12.2007, 12:53
PM ICQ   Вверх
amg
Дата 6.12.2007, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(Ramirez @  6.12.2007,  12:46 Найти цитируемый пост)
Собственно, сам data dumper определяет следующим образом:
Не, это не то. И 1 и '1' подходят под это рег. выражение, да иначе и быть. Наверное, чтобы определить, где число, а где строка, надо смотреть на их представление непосредственно в памяти. Только я никак не могу придумать, зачем бы это могло понадобиться.

PM MAIL   Вверх
pompei
Дата 6.12.2007, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

Репутация: 2
Всего: 6



Мне это нужно для передачи данных в JavaScript.
Например, перловскую конструкцию:
Код

my $x = {
  asd=> 1,
  dsa=> '1',
  u=> [123, '123'],
};

перевести в строку: '{ "asd": 1, "dsa" : "1", "u" : [123, "123"] }'
которую передать в JavaScript, где прогнать её через фукнцию eval, и получить уже яваскриптовую конструкцию. Есть вариант всё представлять в виде строк, но это не красиво, и в общем то меня не устраивает.

Добавлено @ 13:45
Цитата(Ramirez @ 6.12.2007,  12:46)
Код

$val =~ /^(?:0|-?[1-9]\d{0,8})\z/ # safe decimal number


Это не то. для 1 и "1" - это условие даёт один результат, а мне надо чтобы отличатлся.

Dumper-же как-то отличает строку от числа. Вопрос: как он это делает? Найти бы то место, где он это делает, и сделать так же. У меня это не получается. И дебаггер внутрь там одной функции лесть не хочет - проскакивает как "step over", когда я командую "step into".

У меня пока вот так это реалицуется:
Код

#-------------------------------------------------------------------------------
sub _strToJSStr {
    my $s = shift;
    return "$s" if _isNumber( $s );
    $s =~ s/"/" + '"' + "/gm; #"
    $s =~ s/\\/\\\\/gm;
    $s =~ s/\n/\\n/gm;
    $s =~ s/\r/\\r/gm;
    return '"' . $s . '"';
}
#-------------------------------------------------------------------------------
sub _isNumber {
    my $x = shift;
    use Data::Dumper;
    my $y = Dumper( $x );
    return $y !~ /'/; #если есть апостроф, то у нас строка'
    # уродливая функция
}
#-------------------------------------------------------------------------------
sub serializeToJS {
    my $data = shift;
    return 'null' unless defined $data;
    my $ref = ref $data;
    if ($ref eq 'HASH') {
        my $ret = "{";
        my $first = 1;
        while (my ($k, $v) = each %$data) {
            if ($first) {
                $first = 0;
            } else {
                $ret .= ", ";
            }
            $ret .= _strToJSStr( $k ) . ' : ' . serializeToJS( $v );
        }
        return $ret . "}";
    }
    if ($ref eq 'ARRAY') {
        my $ret = '[';
        my $first = 1;
        for my $d (@$data) {
            if ($first) {
                $first = 0;
            } else {
                $ret .= ", ";
            }
            $ret .= serializeToJS( $d );
        }
        return $ret . ']';
    }
    if ($ref eq '') {
        return _strToJSStr( $data );
    }
    die "Cannot serialize $ref";
}
#-------------------------------------------------------------------------------


Это сообщение отредактировал(а) pompei - 6.12.2007, 14:15
--------------------
А всё оказывается гораздо проще: пассивные наноструктуры - активные наноструктуры - системы наносистем - молекулярные наносистемы - сингулярность! По пять лет на каждый этап.
PM MAIL   Вверх
amg
Дата 6.12.2007, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Кстати, насчет eval: 
Код

print Dumper '1';
print Dumper eval('1');


PM MAIL   Вверх
amg
Дата 6.12.2007, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



И как насчет этого?
Код

$_ = '{ "asd": 1, "dsa" : "1", "u" : [123, "123"] }';
s/"((?:[^"]|(?<=\\)")*)"/is_number($1) ? $1 : "\"$1\""/eg;
sub is_number { shift =~ /^(?:0|-?[1-9]\d{0,8})\z/ }
print;


PM MAIL   Вверх
pompei
Дата 6.12.2007, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

Репутация: 2
Всего: 6



Наоборот. Мне надо сложную структуру данных с перла передать в яваскрипт (иерархию сколькоугодно вложенных друг в друга массивов и хэшей содержащие числа и строки), чтобы на яваскрипте была точно такая же иерархия. Я преобразую эту структуру с помощью функции serializeToJS в строку, которую понимает яваскриптовый eval.
--------------------
А всё оказывается гораздо проще: пассивные наноструктуры - активные наноструктуры - системы наносистем - молекулярные наносистемы - сингулярность! По пять лет на каждый этап.
PM MAIL   Вверх
amg
Дата 6.12.2007, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(pompei @  6.12.2007,  13:43 Найти цитируемый пост)
Dumper-же как-то отличает строку от числа. Вопрос: как он это делает? Найти бы то место, где он это делает, и сделать так же. У меня это не получается. И дебаггер внутрь там одной функции лесть не хочет - проскакивает как "step over", когда я командую "step into".
Думаю, что Dumper отличает строку от числа с помощью сишных функций, обращаясь непосредственно к памяти. Возможно, потому и не получается "step into". И если попробовать Data::Dupm (это pure perl) вместо Data::Dumper, то не увидим никакой разницы между 1 и "1".

Добавлено через 2 минуты и 30 секунд
Цитата(pompei @  6.12.2007,  14:51 Найти цитируемый пост)
Наоборот. <...>
Торможу...

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


Опытный
**


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

Репутация: 20
Всего: 27



Эээ, а не проще делать так?
Код

if(is_numeric($var)) { print 'ok' }
else { print 'not ok' }

sub is_numeric { int shift }


UPD:
Сори, прочитал весь топик, понял, что не то. Буду думать)

Это сообщение отредактировал(а) KSURi - 6.12.2007, 17:26


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
Ramirez
Дата 6.12.2007, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 305
Регистрация: 18.1.2005
Где: Moscow, ExUSSR

Репутация: 4
Всего: 5



Так раз вам JSON на выходе нужен, почему бы не воспользоваться 
http://search.cpan.org/~makamaka/JSON-1.15/lib/JSON.pm
а еще лучше
http://search.cpan.org/~mlehmann/JSON-XS-2.01/XS.pm

хотя, он тоже не различает, он все числа без кавычек выдает. разве это критично?

UPDATE: 

JSON-XS в отличие от обычного JSON различает числа в кавычках и нет.

расковырял Data::Dumper и выяснилось, что: он может работать через XS или средствами Perl. По дефолту он использует XS-реализацию. (XS как раз сильно типизирован в отличе от перла, поэтому он правильно обрабатывает числа в кавычках). А вот если Data::Dumper попросить не использовать XS, то он перестает отличать числа от чисел в кавычках:

Код

use strict;

$a = [ 1 , '1' ];


use Data::Dumper;

print "Dumping using XS:\n";
print Dumper($a);

$Data::Dumper::Useperl=1;

print "Dumping using Perl:\n";
print Dumper($a);


на основании этого, смею предположить, что если вы будете использовать XS-реализацию JSON, то получите то, что хотите.

Код

use JSON;                                                                                                                           
use JSON::XS;                                                                                                                       
                                                                                                                                    
$a = [ 1 , '1' ];
                                                                                                                                    
print 'JSON: '.objToJson($a)."\n";                                                                                                  
print 'JSON XS: '.JSON::XS->new->utf8->encode ($a)."\n";


или, если вы принципиально хотите сериализировать самостоятельно, без сторонних модулей, то вам необходимо реализовать подобную проверку на Си и с помощью XS импортировать ее в Perl. Собственно, решение можно подсмотреть в xs-файлах того-же Data::Dumper и JSON-XS.

По другому, видимо - никак....

Это сообщение отредактировал(а) Ramirez - 6.12.2007, 18:32
PM ICQ   Вверх
KSURi
Дата 6.12.2007, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 20
Всего: 27



Наковырял чуть подробнее по XS.

На уровне XS перл представляет скаляр как структуру (SV). В нее может быть загужено 4 типа значений:
  • целочисленное значение (IV)
  • число с плавающей запятой двойной точности (NV)
  • строка (PV)
  • другое скалярное значение (SV)
Для проверки типа хранимого значения (целое; с плавающей точкой; указатель на строку) используются соотвественно следующие макросы:
  • SvIOKp(SV*)
  • SvNOKp(SV*)
  • SvPOKp(SV*)


Это сообщение отредактировал(а) KSURi - 6.12.2007, 18:55


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
vadiml
Дата 6.12.2007, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 7



есть еще и SvUOK(), но с ней проблемы в 64битной сборке
а на уровне XS это действительно делается элементарно:
CheckType.xs
Код

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

Module=CheckType    Package=CheckType

PROTOTYPES: ENABLE

int
ChechVar(SV* sv)
    CODE:
        if ( SvOK(sv) )
            RETVAL=0; // не скаляр
        else if ( SvIOK(sv) )
            RETVAL=1;
        else if (SvNOK(sv))
            RETVAL=2;
        else
            RETVAL=3;
   OUTPUT:
       RETVAL

CheckType.pm
Код

Package CheckType;
require DynaLoader;

our @ISA = qw(DynaLoader);
our $VERSION = '0.01';

bootstrap CheckType $VERSION;

1;


но все проверки достаточно условны, т.е. проверятся в каком контексте последний раз использовалась эта переменная.
а на уровне перла есть только контекст текущего использования
PM MAIL Jabber   Вверх
pompei
Дата 7.12.2007, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

Репутация: 2
Всего: 6



Я искренне всем благодарен за помощь.

ЗЫ. Меня несколько огорчило то, что в чистом перле нельзя это проверить. :(

--------------------
А всё оказывается гораздо проще: пассивные наноструктуры - активные наноструктуры - системы наносистем - молекулярные наносистемы - сингулярность! По пять лет на каждый этап.
PM MAIL   Вверх
pompei
Дата 7.12.2007, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

Репутация: 2
Всего: 6



Цитата(Ramirez @ 6.12.2007,  12:46)

интересно было-бы увидеть надежный способ без регекспов.

Кстати именно для Вашего случая есть решение без герэкспов, довольно надёжное:
Код

use strict;

sub is_number {
    my $x = shift;
    return $x eq (0 + $x);
}

print is_number( "123" ) ? "number" : "string";
print "\n";
print is_number( "asd" ) ? "number" : "string";
print "\n";

вывод:
Код

number
string


Единственное что is_number( "                 123" ) ложно. Но если перед return добавить $x =~ s/^\s+//; то всё нормально. Хотя может быть это как раз таки и не нужно.


 

Это сообщение отредактировал(а) pompei - 7.12.2007, 09:01
--------------------
А всё оказывается гораздо проще: пассивные наноструктуры - активные наноструктуры - системы наносистем - молекулярные наносистемы - сингулярность! По пять лет на каждый этап.
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

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


 




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


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

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