Author Topic: Ошибка из-за вычисление второй части логического И при ложной первой  (Read 6386 times)

0 Members and 2 Guests are viewing this topic.

K7A4

  • Зашел в гости
  • *
  • Posts: 14
    • View Profile
Не только я сталкиваюсь с этой проблемой?

Что-то типа:
Code: (clickermann) [Select]
For($i=0,($i<ArrSize($Arr)-1)&($Arr[$i]<$Arr[$i+1]))
End_Cyc
в некоторых местах приводит к ошибке. Хотя чаще не приводит к ней.
А расписывать эти 2 условия по отдельности - слишком громозко выходит ((

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
А так?
Code: (clickermann) [Select]
For($i=0,($i<ArrSize($Arr)-2)&($Arr[$i]<$Arr[$i+1]))
END_CYC

А то получается если всё нормально и цикл дошёл до последнего элемента массива, сравниваешь с чем $Arr[$i+1]  ?
Вот и ошибка.
Хотя это и не нормально, так писать. Почему не обрабатывать условие сравнения уже внутри цикла. Тогда и таких простых ошибок будет меньше.

И зачем писать в тему ошибки, ошибки в Ваших скриптах? Эта тема для ошибок в самом кликермэне. Зачем людей пугать.
« Last Edit: February 10, 2015, 06:46:08 PM by Vint »


K7A4

  • Зашел в гости
  • *
  • Posts: 14
    • View Profile
Vint, извини, но ты погорячился.
У меня все правильно написано.
Подумай еще раз )

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Наверно да. Попробуй всё условие взять в скобки.
Не помню, но в кликере вроде нигде явно не указано, что вторая часть операнда И не будет вычисляться, если первая дала отрицательный результат. Понятно что так сделано во многих языках для оптимизации. В питоне, например, это явно указано.
В любом случае попробуй скобки. Иногда они необходимы, когда казалось бы вовсе не нужны. Сталкивался с таким.

Но, всё равно пересмотри задание условий. Лучше когда понимаешь с какого по какой элемент будет цикл. Опять же в некоторых языках нельзя изменять переменную цикла. Иногда начальное и конечное значения рассчитываются один раз при старте цикла и изменить их не получится. Вроде в паскале так.
« Last Edit: February 10, 2015, 10:59:18 PM by Vint »


K7A4

  • Зашел в гости
  • *
  • Posts: 14
    • View Profile
Vint, дополнительные внешние скобки пробовал - не помогает.
Я не могу уловить зависимость - в некоторых (большинстве) местах ошибка не выскакивает (цикл останавливается по первому условию), но потом где-нибудь раз - и начинает устойчиво (каждый раз) в одном месте вываливаться ошибка (видно что произошел выход за границы массива).

Насчет ошибки - может я и не прав. Но очень смущает громозкость и низкая читабельность получаемого текста скрипта: при отсутствии функции min ее функционал расписывается минимум 5-ю(!) строчками текста. Можно хотя бы было написать: $Min=If($a<$b,$a,$b)!
Можно написать свою подпрограмму min, но все равно будет 2 строчки (вызов и перенос результата из условного $_Return3 в нужную переменную).

Это все не жалобы. ClickerMann - средство очень хорошее.
Но хочется еще лучше )

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Ну дык, сделано для профанов, вроде меня.
Позиционируется простота и доступность.
А почитав группу, кажется что и то что есть лишнее. Нужно выпилить вплоть до переменных :-)
Лишь бы чертова привязка работала :-)


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Две дополнительных строки сильно не загромоздят. А читабельность так на мой взгляд улучшится.


K7A4

  • Зашел в гости
  • *
  • Posts: 14
    • View Profile
Золотой, столько букв и все в пустую.
В моем скрипте нет выхода за пределы массива если после получения ЛЖИ в первом аргументе операции И обработчик присваивает сразу итоговый результат ЛОЖЬ, не вычисляя второй аргумент.
В бесконечный цикл данная конструкция у меня по факту никогда не уходит.
Но она или работает верно (в одних частях кода) или выдает ошибку (в других) - от чего это зависит я понять не смог.

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Все предсказуемо. Выход за пределы массива в твоем скрипте возможен. Все зависит от данных в $Arr.


Как видно из лога последний номер был 48. А в массиве последняя строка имеет номер 49.
И так у нас 48, цикл выполняется с начала, наращивается переменная $i, мы уже имеем число 49, а далее проверяется условие For($i=0,(49<48)&(49<???)) - вот здесь уже из массива запрашивается 50я несуществующая строка.

Вот так верно.
Code: (clickermann) [Select]
FOR($a=0,$a<50)
   ARRPUSH($arr, $a)
END_CYC

For($i=0,($i<ArrSize($Arr)-2)&($Arr[$i]<$Arr[$i+1]))
   LOGWRITE ("Массив: ", $Arr[$i])
End_Cyc

HALT
« Last Edit: February 11, 2015, 07:28:35 AM by Oraven »

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Короче, порешили. В справке нигде не указано что есть оптимизация вычисления условий. И даже если вторая часть "И" не просчитывается, то предварительный разбор строки может проверять наличие всех необходимых элементов.
Дели на 2 условия и всё
Code: (clickermann) [Select]
FOR($i=0, $i < ArrSize($Arr)-1)
   IF($Arr[$i] < $Arr[$i+1])
      LOGWRITE ("действия при $i = ", $i)
   END_IF
END_CYC


очень смущает громозкость и низкая читабельность получаемого текста скрипта: при отсутствии функции min ее функционал расписывается минимум 5-ю(!) строчками текста. Можно хотя бы было написать: $Min=If($a<$b,$a,$b)!
Можно написать свою подпрограмму min, но все равно будет 2 строчки (вызов и перенос результата из условного $_Return3 в нужную переменную).

Не всё совершенно в этом мире...  :)  Постепенно функции добавляются.

А как начальный кусок скрипта используется при нахождении минимального?
У меня это обычно занимает 6 строк
Code: (clickermann) [Select]
$min = $Arr[0]
FOR($i=1, $i < ArrSize($Arr))
   IF($Arr[$i] < $min)
      $min = $Arr[$i]
   END_IF
END_CYC


K7A4

  • Зашел в гости
  • *
  • Posts: 14
    • View Profile
Oraven, спасибо за конструктивизм и конкретику (в отличии от балабольства выше), но, сорри, ты само название темы видел?
Твое выделенное жирным шрифтом выражение должно выглядеть так: For($i=0,(49<49)&([49]<[50])), однако я небезосновательно рассчитываю, что выражение [49]<[50] не должно даже начинать вычисляться после тога как 49<49=ЛОЖЬ.

Vint, "Дели на 2 условия и всё": всё, да не всё.
А если в массиве не 5, 10 или 50, а 10 тыс. элементов?
А если он сам во втором цикле еще на 10 тыс. повторов, и это внутри нескольких сотен проходов?
Мне надо чтобы цикл останавливался не только по счетчику, но и по условию.
А Break или чего-то подобного нет. А значит не избежать что-то вроде:
Code: (clickermann) [Select]
$Stop=0
For($i=0,($i<ArrSize($Arr))&($Stop=0))
   If($Arr[$i]<$Arr[$i+1])
      $Stop=1
   End_If
End_Cyc
Вот уже и 6 строк (не считая отладочного LogWrite)
В конце-концов можно и без цикла сравнить 50-100 элементов какой-то тысячей-другой строк кода. Но зачем? )

А насчет нахождения минимального - я привел просто в качестве примера.
И имел ввиду нахождение минимального именно из двух значений.
Не обидно расписать приведенный тобою текст из 6 строк для массива, а вот 5 строк ради функционала min($a,$b) - это жестко.
Своя подпрограмма - это уже хорошо.
Но может разрешат делать их функциями и возвращать через имя функции результат?  :P

K7A4

  • Зашел в гости
  • *
  • Posts: 14
    • View Profile
Приведенный мною выше кусок кода можно попробовать переписать:
Code: (clickermann) [Select]
$Continue=1
For($i=0,($i<ArrSize($Arr))&$Continue)
   $Continue=$Arr[$i]<$Arr[$i+1]
End_Cyc
но я уже боюсь за $Continue=$Arr[$i]<$Arr[$i+1] - можно ли так в ClickerMann'е?

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Твое выделенное жирным шрифтом выражение должно выглядеть так: For($i=0,(49<49)&([49]<[50])), однако я небезосновательно рассчитываю, что выражение [49]<[50] не должно даже начинать вычисляться после тога как 49<49=ЛОЖЬ.
Ну раз считаешь, хорошо. Осталось заставить так считать кликер, для чего нужно убедить Джонни.
Только так происходит не во всех языках. И в этом варианте кроются свои подводные камни, Когда во второй части пользовательская функция, например, не существует или работает неправильно. Вот весело это заметить после месяцев правильной работы программы.
В любом случае это только предложение, а не ошибка. Тему я из ошибок перенесу. Попозже.

Vint, "Дели на 2 условия и всё": всё, да не всё.
А если в массиве не 5, 10 или 50, а 10 тыс. элементов?
И что от этого изменится? Добавится хоть строчка кода?
С другой стороны задачи и назначение кликера несколько другое, чем обрабатывать массивы по 10 тыс. элементов. Скорость не та. И сам не захочешь.

А Break или чего-то подобного нет. А значит не избежать что-то вроде:
Code: (clickermann) [Select]
$Stop=0
For($i=0,($i<ArrSize($Arr))&($Stop=0))
   If($Arr[$i]<$Arr[$i+1])
      $Stop=1
   End_If
End_Cyc
Вот уже и 6 строк (не считая отладочного LogWrite)

Ну и что, из-за одной строки $Stop=1 мир рухнул? Не экономь на копейках, будь шире душой  :)

Там для выхода действительно нужно добавить только одну строку
Code: (clickermann) [Select]
FOR($i=0,$i < ArrSize($Arr)-1)
   If($Arr[$i] < $Arr[$i+1])
      $i = ArrSize($Arr)
   End_If
END_CYC
И в твоём варианте всё равно споткнётся на 3 строке.
Ты либо ходиши по всем элементам кроме последнего и сравниваешь. Или ходишь по всем, тогда сравнение для последнего нужно исключить дополнительно.

Не обидно расписать приведенный тобою текст из 6 строк для массива, а вот 5 строк ради функционала min($a,$b) - это жестко.
Своя подпрограмма - это уже хорошо.
Но может разрешат делать их функциями и возвращать через имя функции результат?  :P
Никто не против min($a,$b) и max($a,$b), а так же break, continue, и возвращаемые значения.
Но их просто пока нет. Вот нет и всё.

Тут в функцию через параметры массивы не передаются и не все виды строк, вот где засада.
« Last Edit: February 11, 2015, 11:54:53 AM by Vint »


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Приведенный мною выше кусок кода можно попробовать переписать:
Code: (clickermann) [Select]
$Continue=1
For($i=0,($i<ArrSize($Arr))&$Continue)
   $Continue=$Arr[$i]<$Arr[$i+1]
End_Cyc
но я уже боюсь за $Continue=$Arr[$i]<$Arr[$i+1] - можно ли так в ClickerMann'е?
Правильно боишься, в ClickerMann'е нельзя. Да и не только в нём, наверно нигде нельзя  :) :D


Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Quote
... однако я небезосновательно рассчитываю, что выражение [49]<[50] не должно даже начинать вычисляться после тога как 49<49=ЛОЖЬ.

Кликер читает строку кода из памяти, интерпретатор разбирает писанину, понимает что имеет дело с циклом FOR, что ему нужно увеличить $i, далее заменяет переменные данными (49<49)&([49]<[50]) И вот тут при попытке считать не существующую строку из массива выходит ошибка!

Ошибка происходит на уровне разбора данных еще до сравнения!
Все было бы проще если бы кликер сам тебе сказал что ошибка именно в $Arr[$i+1]

« Last Edit: February 11, 2015, 12:51:39 PM by Oraven »