Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];

Вниз

String или Float   Найти похожие ветки 

 
MakNik   (2004-01-26 17:04) [0]

Подскажите, плз., как красиво проверить, является ли строка буквенным представлением числа(Float)?


 
Плохиш_   (2004-01-26 17:07) [1]


> MakNik © (26.01.04 17:04)
> Подскажите, плз., как красиво проверить, является ли строка
> буквенным представлением числа(Float)?

Сначала надо сходить в парикмахерскую и заняться спортом.


 
zamkom   (2004-01-26 17:07) [2]

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


 
AKul   (2004-01-26 17:14) [3]

Если я правильно понял вопрос:
try
R:=StrToFloat(S);
// S - "правильное" вещественное число и в R - его значение
except
// S - "неправильное" вещественное число
end;


 
MakNik   (2004-01-26 17:22) [4]


> AKul © (26.01.04 17:14) [3]

... а без конструкции try ... except можно?


 
Agent13   (2004-01-26 17:24) [5]

Есть способ, унаследованный из паскаля:
Val(S: string; var V; var Code: Integer);
if Code<>0 then
не число


 
zamkom   (2004-01-26 17:25) [6]

MakNik © (26.01.04 17:22) [4]
Без конструкции try ... except никак нельзя иначе при неправильном S у тебя будет выбивать всю конструкцию.


 
VMcL   (2004-01-26 17:29) [7]

Val()


 
AKul   (2004-01-26 17:30) [8]

1. Можно попробовать через Val(S,R,Code).
При правильном числе в S в Code будет 0, в противном случае Code будет содержать номер неверного символа в S.
Если мне не изменяет память DecimalSeparator не влияет на Val - ей всегда необходимо число с разделителем ".". Поэтому, если необходимо перевод числа с ",", то придется подготавливать число.
2. Написать свою функцию.

P.S. А чем через try...except не устраивает?


 
Sandman25   (2004-01-26 17:42) [9]

[8] AKul © (26.01.04 17:30)

Прочтите When to use exceptions из Object Pascal Guide.
В данном случае лучше обойтись без exceptions. Быстрее работать будет.


 
AKul   (2004-01-26 17:56) [10]


> Sandman25 © (26.01.04 17:42) [9]
>
> Прочтите When to use exceptions из Object Pascal Guide.
> В данном случае лучше обойтись без exceptions. Быстрее работать
> будет.

Спасибо конечно за совет, но структурную обработку исключений я знаю.

Да, действительно, при использовании try...except компилятор добавит несколько "лишних" строк кода (несколько манипуляций со стеком и fs:[0]). Но разве увеличение этого кода на несколько тактов процессора (<мкс) будет заметно по сравнению,например, с продолжительностью ввода пользователя?

Кроме того, при "неправильном" числе функция StrToFloat сама вызовет исключение (если его не перехватить) . Думаю пользователю не очень это понравится.


 
Anatoly Podgoretsky   (2004-01-26 18:00) [11]

Пусть правильно вводит, а не обижается.


 
AKul   (2004-01-26 18:07) [12]


> Anatoly Podgoretsky © (26.01.04 18:00) [11]
> Пусть правильно вводит, а не обижается.


Нехороший у Вас стиль программирования, Anatoly Podgoretsky.


 
Sandman25   (2004-01-26 18:07) [13]

[10] AKul © (26.01.04 17:56)

Я только что специально сравнил код, получаемый при
try
R := strtofloat(Edit1.Text);
except
R := 0;
end;
и при
Val(Edit1.Text, R, Code);
if Code<>0 then
R := 0;

Хотя я и небольшой спец по ассемблеру, но убедился, что Help не соврал. Для try except добавляется куча лишних операций.


 
AKul   (2004-01-27 09:21) [14]


> Sandman25 © (26.01.04 18:07) [13]


> Хотя я и небольшой спец по ассемблеру, но убедился, что
> Help не соврал. Для try except добавляется куча лишних операций.

Как же Вы сравнивали, если Вы "не большой спец по ассемблеру"?
При добавлении try компилятор добавляет всего 3(4) операции (команды).
При Except - ничего (0 операций), адрес этого обработчика передается в одной из строчек try
При End - обработчик просто удаляется из списка (опять же 2-4 операции).
Получается, что "лишних" операций совсем не куча.

Если же рассматривать
Val(Edit1.Text, R, Code);
if Code<>0 then
R := 0;
то для Val необходимо передать не 1 параметр, как в StrToFloat, а 3 (сами понимаете, что это тоже код),
кроме того, команда сравнения Code<>0 тоже код (как минимум 2 операции, да и к тому же условный переход неблагоприятно влияет на конвейерную обработку команд процессора).
Как тогда рассматривать эти "лишние" операции?????
Можно конечно сравнить еще и быстродействие и StrToFloat с Val, но это будет уже отклонение от темы.
И как быть с тем, что внутри StrToFloat сама вызывает исключение в случае ошибки? А если его не перехватить?
Кроме того, структурная обработка исключений повышает надежность программы...

А на счет быстродействия - это все зависит от способа реализации.


 
Anatoly Podgoretsky   (2004-01-27 09:28) [15]

AKul © (26.01.04 18:07) [12]
Ты не прав, пользователи благодарны, что их не втискивают в узкие рамки масок и прочего, а дают возможность вводить, так как они желают и в случае ошибки выдают сообщение, которую они тут же исправляют. А вот в остальных случаях большии обиды на программу.
Поэтому завернув в блок try except или позволив сделать это системе, мы идем навстречу пользователю. Какой выбрать обработчик ошибки свой или системный уже не так важно.


 
AKul   (2004-01-27 09:43) [16]


> Anatoly Podgoretsky © (27.01.04 09:28) [15]
> Ты не прав, пользователи благодарны, что их не втискивают
> в узкие рамки масок и прочего, а дают возможность вводить,
> так как они желают и в случае ошибки выдают сообщение, которую
> они тут же исправляют.

В чем я не прав?
Где Вы здесь упоминалось хоть какое-то подобие втискивания пользования в рамки и маски?
Здесь этот вопрос даже и не рассматривался!

Разве, например, такой код хоть чем-то ограничит пользователя:
try
R:=StrToFloat(Edit1.Text);
// Все нормально идем дальше
except
ShowMessage("Вы ввели ИНВАЛИДНОЕ число....");
Edit1.SetFocus;
exit;
end;
// R - Valid!
.....

А на счет этого:

> Пусть правильно вводит, а не обижается.

то как быть с механическими ошибками, опечатками (ведь от этого никто не застрахован)?


 
Anatoly Podgoretsky   (2004-01-27 10:06) [17]

Не ограничит, поскольку я как раз и говорю, надо обработать самым надежным способом и дать знать пользователю знать об ошибке, поэтому мне теперь непонятно, почему ты тогда написал такое в AKul © (26.01.04 18:07) [12] а сейчас пишешь по моему предложению, какая то непоследовательность!

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


 
Bel   (2004-01-27 10:12) [18]

> MakNik ©

А функции TryStrToFloat, TryStrToFloatDef, StrToFloatDef не помогут?


 
AKul   (2004-01-27 10:29) [19]


> Anatoly Podgoretsky © (27.01.04 10:06) [17]


> а сейчас пишешь по моему предложению, какая то непоследовательность!

Во-первых, код приведенный в [13],я сначала написал в [3], но подумав, что автор вопроса вдруг чего-нибудь не поймет, заменил вывод сообщения об ошибке и установку фокуса на комментарий.
Во-вторых, где Вы хоть раз в моих постах видели хоть мало-мальски похожую на втискивание пользователя в "рамки и маски", покажите, а то мне самому интересно.
В-третьих, В [12] содержится ответ на Вашу фразу " Пусть правильно вводит, а не обижается". Ее я понимаю как "если пользователь ошибся при вводе, то программа должна молча пропустить это, получить "неизвестно что", и это "неизвестно что" использовать дальше при работе, ничего не сказав пользователю, а неверный результат, непонятно как получившийся, - это его проблемы...".
И тут вдруг Вы начинаете утверждать, пользователю все-таки надо сообщать о неверно введенных данных.

Так что это у Вас наблюдается какая-то непоследовательность.


 
AKul   (2004-01-27 10:45) [20]

Bel © (27.01.04 10:12) [18]:
В Delphi5 (то что просил автор вопроса) таких функций нет.
Если это функции какой-то дополнительной библиотеки, то сообщите ее для MakNik ©


 
Bel   (2004-01-27 11:04) [21]

> В Delphi5 (то что просил автор вопроса) таких функций нет.

Не знал, что в D5 их нет. В D6 они есть в модуле SysUtils. Кстати, все они используют функцию TextToFloat, может, она есть в D5?

PS. Про одну функцию я наврал, каюсь, TryStrToFloatDef - такой нету.


 
AKul   (2004-01-27 11:10) [22]


> Bel © (27.01.04 11:04) [21]

Вот функция TextToFloat наверное и есть самое подходящее для MakNik ©.


 
Anatoly Podgoretsky   (2004-01-27 12:04) [23]

AKul © (27.01.04 10:29) [19]
Ты не правильно понимаешь, имено пусть исправляет, а не обижается на сообщение, но если ты берешься за меня додумывать, то это конечно твое право, но вывод неверный.


 
AKul   (2004-01-27 12:09) [24]


> Anatoly Podgoretsky © (27.01.04 12:04) [23]
> Ты не правильно понимаешь

Интересно, а как по другому можно воспринять фразу "Пусть правильно вводит, а не обижается".
P.S.: А что бы за Вас не додумывали, яснее выражайтесь.


 
Sandman25   (2004-01-27 12:16) [25]

[14] AKul © (27.01.04 09:21)

Чтобы сравнивать, не нужно быть большим спецом. Достаточно разбираться на необходимом уровне.
1. Есть try.
Всего 23 операции, из которых 2 jmp и 1 CALL @DoneExcept.
В DoneExcept 15 операций, из которых 3 других CALL: @GetTLS, TObject.Free и FreeNotify.
В GetTLS выполняется по крайней мере 6 операций.
Про TObject.Free с его BeforeDestruction, ClassDestroy и Free рассказывать?
Про FreeNotify?
2. Нет try.
Всего 13 операций, из которых всего 1 jz и нет ни одного дополнительного CALL, кроме тех, что должны быть: TControl.GetText (есть и в 1 случае) и ValExt вместо StrToFloat.

Хотите, чтобы я еще сравнил ValExt с StrToFloat и доказал, что первый работает быстрее и занимет меньше кода? Так Вы из меня большого спеца по ассемблеру сделаете :)

PS. Оптимизация включена, Delphi6.
procedure TForm1.Button1Click(Sender: TObject);
var
r: real;
begin
showmessage("1");
try
R := strtofloat(Edit1.Text);
except
R := 0;
end;
showmessage(floattostr(r));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
r: real;
code: integer;
begin
showmessage("1");
Val(Edit1.Text, R, Code);
if Code<>0 then
R := 0;
showmessage(floattostr(r));
end;


 
AKul   (2004-01-27 13:05) [26]


> Sandman25 © (27.01.04 12:16) [25]
>
> Чтобы сравнивать, не нужно быть большим спецом. Достаточно
> разбираться на необходимом уровне.

Что бы сравнить количество строчек кода - согласен, спецом быть не нужно.
Но чтобы понять что будет выполняться, а что нет - вот тут Вы ошибаетесь.
Да, при try... except строчек кода будет больше, но если исключения не произойдет, никакие CALL @DoneExcept и т.п. не вызовутся.
А если произойдет, согласен, программе нужно будет выполнить ряд дополнительных операций, но за ними же все равно обычно последует вызов с сообщением пользователю (так что тут быстродействие роли не играет).
Насчет быстродействия ValExt и StrToFloat я же написал: "Можно конечно сравнить еще и быстродействие и StrToFloat с Val, но это будет уже отклонение от темы.". Спору нет, что Val будет работать быстрее, но мы же здесь рассматриваем быстродействие кода с try и без него (т.е. с дополнительными проверками), а не быстродействие вызываемых процедур.
Кроме того, Val - функция с меньшими возможностями, чем StrToFloat, но это, конечно, дело вкуса.
P.S.:
Я не собираюсь оспаривать необходимость применения структурной обработки исключений - это как кому захочется (лично я сам ими пользуюсь только в экстренных ситуациях).
Но утверждать, Sandman25 ©, что структурная обработка исключений - это плохо, она делает программы очень медленными, не стоит.
Быстродействие программы больше всего зависит от способа реализации, а не от того, используются ли в ней try...except или нет.
Кроме того, применение структурной обработки исключений повышает НАДЕЖНОСТЬ Вашей программы.
Что из того, если программа на несколько микросекунд будет выполняться дольше (вряд ли кто-то это заметит), но при этом будет более отказоустойчивой?
Как Вы думаете, что пользователю больше понравится:
- то что программа работает на 2 мкс (в сумме) быстрее (правда в системе с вытесняющей многозадачностью такое сравнение выполнения по времени - абстрактно), но "вылетает" при каком-нибудь сбое;
- или то что программа работает стабильно, но на 2 мкс медленнее?


 
Sandman25   (2004-01-27 13:22) [27]

[26] AKul © (27.01.04 13:05)

Почитайте все-таки топик when to use exceptions. Я try-except/finally уже лет 7 успешно использую, и все-таки только недавно его прочитал и открыл для себя много нового и интересного :) Говоря по-простому, если операция критическая и неконтролируемая (открытие файла, выделение ресурса, создание объекта) или же ее очень трудно обработать с помощью 1-2 if, то нужен try except/finally.
Если же можно обойтись без него, то рекомендуют без него обойтись.
Если можно его заменить на 1-2 if, то необходимо без него обойтись.

По поводу нашего спора. Даже если except не срабатывает, выполняется 11 лишних операций по сравнению с 4 (2 на загрузку параметров и 2 на cmp и jz)

PS.
P1 := ...
try
P2 := ...
try
..
finally
P2.Free;
end;
..
finally
P1.Free;
end;

очень структурно, не спорю. Но быстрее будет работать
P1 :=
try
P2 :=
finally
if Assigned(P2) then
P2.Free;
P2.Free;
end;


 
Sandman25   (2004-01-27 13:22) [28]

В конце P1.Free, конечно.


 
Sandman25   (2004-01-27 13:41) [29]

Точнее, так:
P2 := nil;
P1 := ...
try
P2 :=
finally
P2.Free;
P1.Free;
end;


 
AKul   (2004-01-27 14:11) [30]


> Sandman25 © (27.01.04 13:22) [27]

На счет:
> Если же можно обойтись без него, то рекомендуют без него
> обойтись.
> Если можно его заменить на 1-2 if, то необходимо без него
> обойтись.

Я согласен, (сам так делаю),
но вот отказываться в критических ситуациях из-за того, что он будет чуть-чуть медленнее работать - никак нет.


> По поводу нашего спора. Даже если except не срабатывает,
> выполняется 11 лишних операций по сравнению с 4 (2 на загрузку
> параметров и 2 на cmp и jz)

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


 
Sandman25   (2004-01-27 15:43) [31]

[30] AKul © (27.01.04 14:11)

...но вот отказываться в критических ситуациях из-за того, что он будет чуть-чуть медленнее работать - никак нет.

Господи, да я где я такое писал?!

У некоторых есть тенденция учить начинающих, что если происходит какая-то ошибка, то просто ставь try except. И доходит до того, что пишут
try
Table.Post;
except
end;
вместо того, чтобы написать
if Table.State in [dsEdit, dsInsert] then
Table.Post;

К Вам это не относится, у меня просто накипело уже :)
try/except - это не панацея, это такой же оператор как и другие. Ведь не ставят же люди лишний for или while от того, что им лень подумать и написать пару строк кода!

А по поводу ассемблера я спорить не буду, уж простите великодушно :)



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.041 c
14-16719
MYSTERYO
2004-01-16 17:17
2004.02.06
Вот заметил веселую вещь при входе в чат


4-16827
Reanimator
2003-11-30 23:28
2004.02.06
Как по хендлу окна получить путь к екзешнику


1-16379
Olphi
2004-01-23 18:13
2004.02.06
Как выровнять текст по ширине в TMemo или TRichEdit?


3-16177
sveta
2004-01-15 06:22
2004.02.06
Кодировка ч/з dbExpress


7-16748
Andrew287
2003-11-21 01:39
2004.02.06
Остановка службы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский