:: Visual Foxpro, Foxpro for DOS
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
ABB
Первая и главная - понимание кода.
Неужели рекурсия в данном случае повышает понимание по сравнению с циклом?
По-моему, как раз наоборот - вам же надо просто пробежаться по строке слева направо,
так каким же образом рекурсия улучшает понимание того, что и так предельно ясно?

ABB
Не нравится рекурсия - к вашим услугам простой цикл.
Лозунг ""Экономь миллисекунду" не всегда хорош.
Да, в этом случае не нравится - обычный цикл кажется более естественным.
Но с тем, что скорость не всегда выходит на первый план, полностью согласен.
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
chunihin-df
Подозреваю, что GETWORDNUM(SYS(15, PADR(SPACE(47)+[0123456789], 255), m.lcStr), 1) отработает за такое же время,
что и GETWORDNUM(SYS(15, tabl, m.lcStr), 1)
Лень проверять, так как и без этого очевидно, что первый вариант будет работать несущественно медленнее -
на секунды, а не в разы (при тех же 10^8 итерациях), ведь выполнить несколько операций (и 2 функции) - дольше,
чем просто взять уже готовое значение.
И эта разница должна быть больше, чем разница между константой и переменной.

chunihin-df
не знаю стоит ли переживать из-за распухания fxp
Не переживать, а беспричинно допускать.



Исправлено 1 раз(а). Последнее : akvvohinc, 24.12.24 15:16
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
Цитата:
NOT BETWEEN(ASC(LEFT(LTRIM(lcStr),1)), 48, 57)
Да, так и приходилось когда-то писать, пока не появился ISDIGIT().

Кстати, здесь как раз интересный пример того, что упрощение выражения приведет
к приличному увеличению времени исполнения.
Имею в виду функцию BETWEEN(), которая принимает не только числовые аргументы,
и можно было бы обойтись без превращения символа в число:
BETWEEN(LEFT(LTRIM(lcStr),1), '0', '9')

И так действительно понятнее, что здесь делается.
Вот только со строками BETWEEN() работает прилично медленнее.
Но если время не критично, то из этих двух я бы выбрал строковый вариант, соглашаясь с ABB
ABB
Первая и главная - понимание кода.



Исправлено 1 раз(а). Последнее : akvvohinc, 24.12.24 16:18
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
chunihin-df

Сообщений: 94
Откуда: Тюмень
Дата регистрации: 18.11.2013
Цитата:
Цитата:
NOT BETWEEN(ASC(LEFT(LTRIM(lcStr),1)), 48, 57)
Да, так и приходилось когда-то писать, пока не появился ISDIGIT().

Наверное, можно еще сложнее выражение сделать, только вот на время выполнения isdigit, between, ltrim, asc почти не оказывают влияния.

Вот, например, сравнил GETWORDNUM(SYS(15, PADR(SPACE(47)+[0123456789], 255), lcStr), 1) и GETWORDNUM(SYS(15, m.tabl, lcStr), 1)
100 000 000 итераций
строка: REPLICATE("123456test", 100)
В результате получается +/- одно и то же время, не исключаю, что при нескольких запусках время выполнения может меняться местами: выражение будет чуть медленнее, переменная чуть быстрее
выражение: 444.947 с
переменная: 450.144 с
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
ABB

Сообщений: 165
Откуда: Санкт-Петербург
Дата регистрации: 21.10.2006
akvvohinc
так каким же образом рекурсия улучшает понимание того, что и так предельно ясно?
Никаким, это было - а могу ли я ....
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
Цитата:
не исключаю, что при нескольких запусках время выполнения может меняться местами: выражение будет чуть медленнее, переменная чуть быстрее
Так не должно быть, если условия одинаковы.

Но раз так, то пришлось всё же не полениться - убрал все задачи, которые могут влиять на производительность
и запустил сравнительные тесты (ваш вариант, но без GETWORDNUM(), который только испортит картинку)
поочередно по 3 раза каждый, каждый раз выходя из Фокса.

Результаты:
Переменная: 168, 171, 169, средняя = 169
Выражение: 176, 176, 177, средняя = 176

* поочередно оставлял то один коммент в цикле, то другой
tabl = PADR(SPACE(47)+'0123456789',255)
teststr = REPLICATE("123456test", 100)
sec = SECONDS()
FOR i=1 TO 10^8
* SYS(15, tabl, teststr)
* SYS(15, PADR(SPACE(47)+'0123456789',255), teststr)
ENDFOR
? SECONDS()-sec

Но еще правильнее было бы сравнивать именно то, что нам нужно:
= tabl
= PADR(SPACE(47)+'0123456789',255)

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



Исправлено 4 раз(а). Последнее : akvvohinc, 24.12.24 18:42
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
chunihin-df

Сообщений: 94
Откуда: Тюмень
Дата регистрации: 18.11.2013
Да, конечно, переменная должна быть быстрее, чем выражение, даже странно, что получилось наоборот.
До 10^7 итераций включительно так и было: с переменной выполнялось чуть быстрее, на 10^8 получилось как получилось )

Я чуть иначе тестировал: в первом prg определил prg функции, а вызывал из второго prg.
m.tabl объявлена как PRIVATE во втором prg , потому что я не умею так, чтобы переменная была определена в том же prg что и функция, и значение ей бы присваивалось 1 раз.

FUNCTION valex1(lcStr)
RETURN SYS(15, PADR(SPACE(47)+[0123456789], 255), lcStr)
ENDFUNC
FUNCTION valex2(lcStr)
RETURN SYS(15, m.tabl, lcStr)
ENDFUNC
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
chunihin-df
Я чуть иначе тестировал
Чаще всего интересует вопрос не на сколько один вариант быстрее, а во сколько раз.
И поэтому в тестах на скорость желательно убирать всё лишнее, что может повлиять на общее время выполнения,
так как одно дело 10/5 = 2 и совсем другое (10+20)/(5+20) = 1.2.
Вот эти одинаковые и ненужные для правильной оценки 20 желательно из проверки исключить.

А раз здесь мы хотели определить время, с которым извлекается значение переменной и время вычисления выражения, то в идеале должен был остаться только цикл (его не уберешь, но в идеале можно учесть и время выполнения пустого цикла) и одна строка внутри в "минимальном исполнении":
= tabl
= PADR(SPACE(47)+'0123456789',255)

PS
Заодно вспомнил, что когда-то удивился, когда узнал, что доступ к переменной, написанной с префиксом M.,
выполняется дольше, чем без него.



Исправлено 2 раз(а). Последнее : akvvohinc, 24.12.24 20:07
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
chunihin-df

Сообщений: 94
Откуда: Тюмень
Дата регистрации: 18.11.2013
Так сразу было понятно, что sys(15) это O(N), а chrtran - О(NM), грубо говоря sys(15) в m раз быстрее
Дальше оценивать - только себя расстраивать, например без определения функции 10^8 итераций выполняются за 160 с, а с функцией за 460



Исправлено 1 раз(а). Последнее : chunihin-df, 24.12.24 21:15
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
chunihin-df

Сообщений: 94
Откуда: Тюмень
Дата регистрации: 18.11.2013
И в целом печально, что если в фоксе сделать вот так
str = "123456test".repeat(100); re = new RegExp("[0-9]+", "i"); for(i=0;i<1000000000;i++) { found = str.match(re); }
то можно смело идти спать, чем ждать пока он закончит

Даже вот это выполняется секунд 10, что не новость конечно
FOR i = 1 TO 1000000000
ENDFOR
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
Цитата:
Даже вот это выполняется секунд 10, что не новость конечно
Оптимистично.
Но на моей системе - полноценные 22 сек.
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
chunihin-df

Сообщений: 94
Откуда: Тюмень
Дата регистрации: 18.11.2013
Это еще что, вот если запустить такое же в MSSQL, то даже не знаю стоит ли ждать пока он закончит

declare @i int = 1;

while @i < 1000000000
begin
set @i = @i + 1
end;

Ладно, do while в фоксе тоже не особо хорош, но не настолько плох
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
of63

Сообщений: 26001
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Равиль
Привет !
Случайно нарвался ... хотел простейший способ извлечь первую цифровую часть строки

? VAL("123ghj0821106c")
? VAL("123567qwer0821106c")

? VAL("56e0821106c") && ошибка переполнения (вычисляет как e в степени)

*!* ps Пришлось сделать так, подменяя символы "eE" на что-то другое, например "|"

? VAL(CHRTRAN("56E082kl116706c","eE","||"))

А в виде какого числа хочется получить "VAL" от "56e0821106c" ? как VAL("560821106") или как VAL("56"), или как VAL ("56e0821106") ?
Не понял, почему замена небукв именно на вертикальную палку?
Почему не поставить задачу определеннее, тогда и ответ(ы) возникнут определеннее...
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
Владимир Максимов

Сообщений: 14146
Откуда: Москва
Дата регистрации: 02.09.2000
akvvohinc
Владимир Максимов
Простейший способ оставить только цифры - это сначала заменить цифры, а затем полученную строку использовать как маску исключения.
Не согласен.

Проще использовать одну функцию SYS(15), чем две CHRTRAN():
1) такой алгоритм гораздо понятнее - ведь сразу делается именно то, что требуется.
2) да и работать будет в 20-30 раз быстрее (и чем длиннее строка, тем большим будет выигрыш в скорости)

Понятность

99% времени разработчик тратит не на написание кода, а на его изучение. Поэтому критерий "понятности кода" должен стоять на одном из первых мест. Но здесь вопрос в том, а что именно вкладывается в термин "понятности"? Как правило, под этим понимают "привычность". "Пусть безобразно, зато единообразно" (c)

С этой точки зрения SYS(15) - предельно НЕ понятная конструкция по той причине, что используется крайне редко и мало кто вообще в курсе, что такая функция есть. Описание, конечно, можно почитать, но начало справки по этой функции "включена для обратной совместимости". Т.е. такие функции следует использовать только и исключительно тогда, когда других способов нет вообще. Не лучше/хуже, а именно "вообще нет" (есть причины для этого)

С другой стороны, функцию ChrTran() используют достаточно часто и что она делает и как - всем понятно.

Насчет "сразу делается", так ChrTran() тоже "сразу делает". Первый (вложенный) ChrTran() - это способ формирования маски преобразования. То же самое, что у Вас делается для SYS(15). Тоже ведь "маску" надо подготовить. Отличие только в том, что в моем примере эта "маска" не есть константа. Но можно же и константу сделать - цикл от 0 до 255, исключая коды для цифр

Сравни синтаксис

SYS(15, cTranslationExpression, cTranslated)
CHRTRAN(cSearchedExpression, cSearchExpression, cReplacementExpression)

Не вижу принципиальной разницы с точки зрения "сразу делает". Что для SYS(15) надо предварительно подготовить cTranslationExpression, что для CHRTRAN() надо предварительно подготовить cSearchExpression и cReplacementExpression




ABB
Я предпочел бы следующую функцию

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

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

В FoxPro посимвольный разбор обычно делается через цикл, а не через рекурсию. Просто для данной задачи имеем "вырожденный" случай, который можно решить простой заменой символов по маске

Теоретически, можно еще использовать регулярные выражения, но это еще более непривычный инструмент для разработчика на FoxPro.

Скорость работы

Напоминаю, что FoxPro - это СУБД. Это не есть текстовый редактор. Да, у него есть функции строкового разбора, но они изначально носят "вторичный" характер.

Если возникает задача постоянного поиска, то создается отдельное поле, в которое записывается уже результат преобразования. И, скорее всего, это поле будет заполняться сразу в момент создания записи.

Это значит, что для данной задачи именно скорость - не является чем-то значимым. Носит явно вторичный, не основной характер
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
of63

Сообщений: 26001
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
() как вы вдруг раскопали это раритет, тривиальную функцию SYS(15). Вряд ли она есть камень преткновения, или торможения в чем либо проекте... если есть? )

> Напоминаю, что FoxPro - это СУБД. Это не есть текстовый редактор
Владимир, для нас фокс это не только лишь язык общения с табличками ("БД"), но и ЯП всяких мелких (и текстовых) функций, поэтому мы так щепетильны каждой букве кода!



Исправлено 1 раз(а). Последнее : of63, 09.01.25 21:32
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
Владимир Максимов
такие функции следует использовать только и исключительно тогда, когда других способов нет вообще. Не лучше/хуже, а именно "вообще нет"
Аргумент не принимается, по крайней мере, мною.
Ведь функция SYS(15) появилась гораздо раньше, чем CHRTRAN().
Да и к чему постоянно вспоминать, как использовать SYS(15)?
Один раз написали функцию на её основе и забыли на неопределенное время. А понадобится вновь - у вас уже будет готовый аналог.

Владимир Максимов
Отличие только в том, что в моем примере эта "маска" не есть константа. Но можно же и константу сделать - цикл от 0 до 255, исключая коды для цифр
Но в результате вы получите лишь ухудшенный аналог SYS(15).

Но это бессмысленно, так как даже если отбросить соображения субъективного характера (что логичнее, понятнее и т.п.), то остаётся одно вполне себе объективное отличие - существенная разница в скорости работы.
Ведь даже убрав из вашего решения один CHRTRAN(), оно всё равно будет работать на порядок медленнее, чем SYS(15).

Вот напишете вы один раз свою функцию, основанную на одном или двух CHRTRAN(), а я напишу свою - на SYS(15), после чего всё субъективное навсегда скроется в черном ящике этой функции.
- Что же останется в сухом остатке?
- Лишь скорость их работы.

Владимир Максимов
Это значит, что для данной задачи именно скорость - не является чем-то значимым.
Думаю, что замена (или выделение) набора символов в строке - это не задача, а скорее некая универсальная функция.
А вот в какой именно задаче возникнет необходимость в её использовании, заранее неизвестно.
А поэтому при прочих равных (или почти равных) я всегда выберу более быстрый способ получения результата.

Своё понимание того, какой способ более логичен и понятен, я описал выше.
Но в любом случае отличия здесь не кардинальны, чтобы быть решающими.



Исправлено 1 раз(а). Последнее : akvvohinc, 10.01.25 05:46
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
of63

Сообщений: 26001
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
> @более быстрый@ )))

() заранее не удалось сказать заранее какой путь "более быстрый", был путь "чтобы работало", а потом "убыстри" (если медленно работает)



Исправлено 1 раз(а). Последнее : of63, 16.01.25 21:01
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
Владимир Максимов

Сообщений: 14146
Откуда: Москва
Дата регистрации: 02.09.2000
akvvohinc
Владимир Максимов
такие функции следует использовать только и исключительно тогда, когда других способов нет вообще. Не лучше/хуже, а именно "вообще нет"
Аргумент не принимается, по крайней мере, мною.
Ведь функция SYS(15) появилась гораздо раньше, чем CHRTRAN().

Есть очень много функций, которые были созданы для FoxPro For DOS и до сих пор "включены для обратной совместимости". Однако их почему-то не используют. Странные люди. Например, формы надо вручную через SAY/GET "рисовать". Функции-то раньше появились, чем всякие там графические построители. Разве не так?

akvvohinc
Да и к чему постоянно вспоминать, как использовать SYS(15)?
Один раз написали функцию на её основе и забыли на неопределенное время. А понадобится вновь - у вас уже будет готовый аналог.

Вы получили некий результат, который вызывает у Вас сомнение. Хотите узнать, каким именно образом этот результат был получен. Смотрите код. Там некая непонятная функция SYS(15). Очевидно, придется разбираться, что это такое

akvvohinc
Владимир Максимов
Отличие только в том, что в моем примере эта "маска" не есть константа. Но можно же и константу сделать - цикл от 0 до 255, исключая коды для цифр
Но в результате вы получите лишь ухудшенный аналог SYS(15).

Да, да. Я Вас понял. Форма в построителе - это "ухудшенный аналог SAY/GET". Очевидно же...

akvvohinc
Но это бессмысленно, так как даже если отбросить соображения субъективного характера (что логичнее, понятнее и т.п.), то остаётся одно вполне себе объективное отличие - существенная разница в скорости работы.
Ведь даже убрав из вашего решения один CHRTRAN(), оно всё равно будет работать на порядок медленнее, чем SYS(15).

Фраза "включено для обратной совместимости" - указывается не "по приколу", а по той причине, что никто не дает гарантии корректной работы этой функции при тех или иных условиях. Никто просто не занимался отловам разных багов и глюков для таких функций. Хотите - используйте. Но без претензий, если вдруг выяснится, что при каких-то условиях/настройках результат становится очень странным

Единственная цель "обратной совместимости" только и исключительно в том, чтобы код, написанный в строй версии программы, запустился и отработал. Хоть как-нибудь... А вот насчет красиво/правильно/быстро - никакой гарантии нет

На всякий случай, аргумент "у меня все работает" - не принимается, по той причине, что заранее не известно, какие настройки среды будут в том или ином приложении и какие из них могут оказать влияние на результат работы функции. Т.е. один разработчик не может учесть все возможные сценарии работы (если он не разработчик самого FoxPro, конечно ).
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
akvvohinc
Автор

Сообщений: 4563
Откуда: Москва
Дата регистрации: 11.11.2008
Владимир Максимов
Есть очень много функций, которые были созданы для FoxPro For DOS и до сих пор "включены для обратной совместимости". Однако их почему-то не используют. Разве не так?
Не так.
Я имел в виду, что для меня функция SYS(15) - не экзотика, я ей активно пользовался задолго до появления CHRTRAN().
С её помощью выполнялись, например, операции UPPER() и LOWER() для русских букв в тех версиях Фокса, которые не умели этого делать.

Владимир Максимов
Да, да. Я Вас понял. Форма в построителе - это "ухудшенный аналог SAY/GET". Очевидно же...
Я тоже вас понял - с этого места и до конца пошла очевидная демагогия, не относящаяся к делу.
Мне это неинтересно. :hi:
Ratings: 0 negative/0 positive
Re: ? VAL("56e0821106c")
Равиль

Сообщений: 6692
Откуда: Уфа
Дата регистрации: 01.08.2003
Всем привет !

akvvohinc
Владимир Максимов
Есть очень много функций, которые были созданы для FoxPro For DOS и до сих пор "включены для обратной совместимости". Однако их почему-то не используют. Разве не так?
Не так.
Я имел в виду, что для меня функция SYS(15) - не экзотика, я ей активно пользовался задолго до появления CHRTRAN().
С её помощью выполнялись, например, операции UPPER() и LOWER() для русских букв в тех версиях Фокса, которые не умели этого делать.

Сергей, если Вы застали те времена и находили такие решения - это говорит по крайней мере о двух вещах :
Мы одно поколение и Фокс с нами как верный товарищ не один десяток лет

Владимир Максимов
Да, да. Я Вас понял. Форма в построителе - это "ухудшенный аналог SAY/GET". Очевидно же...
akvvohinc
Я тоже вас понял - с этого места и до конца пошла очевидная демагогия, не относящаяся к делу.
Мне это неинтересно. :hi:

Владимир Максимов конечно же не нуждается в защите, но замечу, что в демагогии он не был замечен,
здесь скорее пошла дружелюбная игра аналогий/терминологий и мы знаем, что она не имеет конца

Да, часто простейшая задача порождает самые непредсказуемые оригинальные решения,
это здорово и познавательно ! Спасибо

Мы с интересом наблюдали это обсуждение на высоком профессиональном уровне,
и к чести нашего клуба, с демонстрацией такта и внимания, взаимного уважения к оппоненту - это правда :hi:

Поскольку тема исчерпана, позвольте по праву ТС попросить закрыть ее.


------------------
Тяжело согнать курсором муху с монитора ...




Исправлено 1 раз(а). Последнее : Равиль, 20.01.25 06:19
Ratings: 0 negative/1 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 13 DenKa  (Гостей: 12)

© 2000-2025 Fox Club 
Яндекс.Метрика