Некорректная работа функции trunc в атрибутах динамических блоков

Автор Тема: Некорректная работа функции trunc в атрибутах динамических блоков  (Прочитано 15628 раз)

0 Пользователей и 3 Гостей просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Всем привет. При создании блока определенной сложности (я пока не понял какой) перестает корректно работать функция trunc в атрибуте блока:

Как видно из скриншота, trunc(4400/100) выдает 43, что кроме как глюком больше никак не назовешь.
Данный простой блок создан путем удаления "кусков" из сложного, в котором и был обнаружен данный глюк.
Заметил такую особенность - если блок потягать ручками, то он начинает считать корректно, если же вбивать через свойства значения длины, то блок неадекватен:

Возможно, кто-то сталкивался и может пояснить, в чем дело и как такое, вообще, может быть?
Хотелось бы отметить, что я несколько лет пользовался функцией trunc во всевозможных ее проявлениях и никогда подобных проблем не было.
Но тут ... подкрался незаметно.
Да, также хотелось бы отметить, что данная проблема имеет место на разных компах с AutoCAD 2016x64 и AutoCAD 2017x64.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Почему trunc, а не round?
Потому что round округляет по правилам математики:
Код - Auto/Visual Lisp [Выбрать]
  1. round(4.3) = 4
  2. round(4.5) = 5
  3. round(4.7) = 5
Чаще всего мне нужно либо целая часть, либо округление в большую сторону:
Код - Auto/Visual Lisp [Выбрать]
  1. trunc(x)
  2. trunc(x + 1)
Ну да, можно было бы, конечно, и при помощи round сделать нечто подобное:
Код - Auto/Visual Lisp [Выбрать]
  1. round(x - 0.5) - округление в меньшую сторону
  2. round(x + 0.5) - округление в большую сторону
Но я привык к trunc.
И у меня есть больше сотни блоков, где я уже пользовался trunc, проблемы начались только сейчас и только в конкретных блоках, но я не могу выделить критерии их возникновения.

UPD.
В общем-то, с round такая же шляпа в пределах моего "кривого" блока.



Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну что же. Увы, но это проблемы с точностью округления. Конечно это баг, но такой тонкий, что им вряд ли кто-то будет заниматься. Так что или переходи на round, или используй в формулах что-то такое: trunc((val1+fuzz)/val2) (например, fuzz = 1e-6):





 
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну и ещё для убедительности, что в таком виде использовать trunc нельзя ни в коем случае (!!!):

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Ну что же. Увы, но это проблемы с точностью округления. Конечно это баг, но такой тонкий, что им вряд ли кто-то будет заниматься.
Если это баг, то почему он проявляется не всегда??
Иногда его удается "вылечить", заменив вхождение блока на такое же, только новое.
Делаю это при помощи самопального метода:
Извините, вам запрещён просмотр содержимого спойлеров.
Так что или переходи на round
В предыдущем посте написал, что в "нездоровом блоке" с round происходит то же самое.
или используй в формулах что-то такое: trunc((val1+fuzz)/val2) (например, fuzz = 1e-6)
:(
А вот еще кое-что интересное по этому поводу: у меня есть 2 одинаковых вхождения блока (блок здорового человека и блок курильщика) в разных документах, вот что происходит, если копировать один в другой:

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Ну и ещё для убедительности, что в таком виде использовать trunc нельзя ни в коем случае (!!!):
Ну так, я бы подстроился, если бы баг был статическим, а получается какой-то генератор случайного округления - иногда так срабатывает, иногда иначе, потом вдруг блок начинает работать как нужно, а через некоторое время снова шляпа (бывают даже случаи, когда ctrl+z решало данную проблему, то есть вот ставишь размер, обновляешь поле, баг, делаешь шаг назад, ставишь тот же размер - все ок :D - на самом деле, это не так и смешно >:().

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
1) Ты моё второе видео смотрел?
2) Ты понимаешь, что если trunc(4399.9999999999999/100) даёт 43, то тебе эта функция не годиться?
3) Там происходят различные арифметические операции над числами плавающей арифметики. Любые операции приводят к потере точности. Соответственно в реальности у тебя не 4400, а что-то около этого. И как результат потеря точности при операции trunc
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
1) Ты моё второе видео смотрел?
Я все Ваши видео по два раза смотрю!
2) Ты понимаешь, что если trunc(4399.9999999999999/100) даёт 43, то тебе эта функция не годиться?
А Вы понимаете, что с round то же самое?

А trunc и round - это все, что имеется!!
То есть мне ничего не годится, кроме костыля с 1e-6.
3) Там происходят различные арифметические операции над числами плавающей арифметики. Любые операции приводят к потере точности. Соответственно в реальности у тебя не 4400, а что-то около этого. И как результат потеря точности при операции trunc
Вопрос из предыдущего поста, почему они происходят по-разному и случайно? Я не понимаю! Вы смотрели мое видео "Чудеса с функцией trunc"?

Отмечено как Решение Максим Маркевич 10-12-2016, 01:02:32

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну так, я бы подстроился, если бы баг был статическим, а получается какой-то генератор случайного округления
Прибавляй 1e-6 - всё будет нормально. И лучше даже так:  trunc((val1/val2)+1e-6)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
То есть мне ничего не годится, кроме костыля с 1e-6.
Им и пользуйся - другого нет и не будет. Это проблема плавающей арифметики. Кстати, уже не раз обсуждавшаяся на этом форуме. И вылезает она в разных местах. В данном случае в полях.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Прибавляй 1e-6 - всё будет нормально. И лучше даже так:  trunc((val1/val2)+1e-6)
Кажется, это один из самых тяжелых моментов в жизни.
Но, спасибо большое, Александр Наумович. Мне стало намного легче.
Думаю, тот факт, что совет использовать костыль дали мне лично Вы, успокоит мой перфекционизм. ;)

Оффлайн Матвей

  • ADN OPEN
  • Сообщений: 23
  • Карма: 1
Здравствуйте. Подскажите, где можно посмотреть синтаксис функций, рассмотренных в данной теме.
В справке (http://help.autodesk.com/view/ACD/2018/RUS/?guid=GUID-F94A885A-4DA2-432B-AC1A-EB49CC6C1C72) не нашел функций round и trunc. Или это вообще не выражения DIESEL?

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Забавно. Данный топик в справке к автокад 2018: http://help.autodesk.com/view/ACD/2018/RUS/?caas=caas/discussion/t5/-AutoCAD-/-trunc-/td-p/6740389.html

А по поводу функций, я так понимаю они вот отсюда:
AutoCAD 2018 Справка: Использование стандартных числовых функций (команда КАЛЬК)
http://help.autodesk.com/view/ACD/2018/RUS/?guid=GUID-8108BA81-9204-4C42-8F61-381DBC472771

Оффлайн Матвей

  • ADN OPEN
  • Сообщений: 23
  • Карма: 1
Владимир Шу, спасибо