Сообщество программистов Autodesk в СНГ
ADN Club => AutoLisp / VisualLISP и DCL => Тема начата: Балиев от 05-08-2015, 18:15:10
-
С недоумением обнаружил, что выражение (числа могут быть любыми):
(< (- 1.3 1.1) 0.1)
принимается AutoLISP'ом как истинное (T).
Стал разбираться. Выяснилось, что граница этого чуда находится на 16 знаке после запятой. Т.е. выражение:
(< (- 1.3000000000000001 1.1) 0.2)
генерирует T, а выражение:
(< (- 1.300000000000001 1.1) 0.2)
уже генерирует nil
Что это было: глюк AutoLISP'а или я матчасть недоучил?
-
С недоумением обнаружил, что выражение:
Код: [Выделить]
(< (- 1.3 1.1) 0.1)
принимается AutoLISP'ом как истинное (T).
Вообще-то nil:
Command: (< (- 1.3 1.1) 0.1) nil
Почитай про плавающую арифметику, про количество значащих цифр в числе типа double, про ошибки округления.
-
Сорри, опечатка вышла. Вместо:
(< (- 1.3 1.1) 0.1)
читать
(< (- 1.3 1.1) 0.2)
-
Сорри, опечатка вышла
Тем не менее всё, что я написал ниже справедливо.
Число двойной точности (https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D0%B4%D0%B2%D0%BE%D0%B9%D0%BD%D0%BE%D0%B9_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D0%B8).
-
Чтобы не было сомнений в чуде. :)
-
Чтобы не было сомнений в чуде.
Я уже третий раз пишу, что это не чудо. И что именно так и должно быть. И это не зависит от языка программирования, а зависит от архитектуры процессора, количества значащих цифр в плавающем числе.
-
Но там же сравниваются два одинаковых числа с плавающей запятой. Если это не так, то в какой момент вычисления образуется разница? Более того, Если ты, скажем, напишешь так:
(setq a (- 1.3 1.1))
(< a 0.2)
То результат будет T. Ты уверен, что так и должно быть?
-
То результат будет T. Ты уверен, что так и должно быть?
Да. Учи матчасть.
Прекрасная статья для этого: http://habrahabr.ru/post/112953/
-
Обнаружился клиент, которому я не могу объяснить про хранение плавающих (double), и точность округления: http://forums.autodesk.com/t5/objectarx/convert-string-to-double-problem-tstof/td-p/6528442
Увы, но и такое бывает... ???
-
Вот тут популярно об этом говорят:
оригинал:
русская версия
-
Столкнутся с похожей ситуацией...
Команда: (+ 40.26 285100.0)
285140.0
Но я жду от этого вычисления 285140.26
Как быть? и как вообще с этим жить?
-
Чего?? А поподробнее? :)
-
Что мне возвращает AutoCAD ну или Lisp кто-то из них
(+ 40.26 285100.0) -> 285140.0
(+ 40.26 85100.0) -> 85140.3
(+ 40.26 5100.0) -> 5140.26
(+ 40.26 100.0) -> 140.26
А я хочу получать во всех случаях .26 на конце
-
(mapcar '(lambda(x) (rtos (+ 40.26 x) 2 )) '(285100. 85100. 5100. 100.)) ; '("285140.26" "85140.26" "5140.26" "140.26")
Может, вопрос в представлении?
P.S. Как раз о точности:
(mapcar '(lambda (x) (rtos (+ 40.26 x) 2 14)) '(285100. 85100. 5100. 100.)) ; '("285140.26" "85140.25999999999" "5140.260000000001" "140.26")
-
Может, вопрос в представлении?
Точно!
Но всё равно странно, в общем я это значение в exl передавал, и оно туда прилетало именно как мне в Lisp представляло, а с rtos всё нормуль, спасибо большое, а то я уже испугался...
-
BearDyugin
Не пользуешься поиском. Это на форуме уже обсуждалось. В командную строку AutoCAD действительное число выводится с точностью 6 десятичных знаков (всего 6 знаков, а не после запятой). Поэтому чем больше число (десятичных разрядов), тем меньше у него знаков после запятой, которые выводятся в командную строку. При этом само число хранится в 64-битах, что обеспечивает точность до 16 десятичных знаков.
-
Не пользуешься поиском. Это на форуме уже обсуждалось.
Я извиняюсь, в Яндекс забивал, но я даже вопрос толком не знал как сформулировать, писал что-то вроде "Lisp округляет вещественные числа" на этом форуме честно просмотрел все 6 страниц ветки про AutoLISP, из самых подходящих нашёл эту тему.
Получается vl-princ-to-string по тому же принципу работает?
-
По идее, насколько я помню, передавать надо через variant. Могу ошибаться.
-
Получается он в Excel тоже через командную строку значения передаёт, или по тем же правилам?
Нет. Вопрос о том, как ты передашь в Excel.
-
Быстро вы ответили с Алексеем, я сообщение уже подредактировал
-
Получается vl-princ-to-string по тому же принципу работает?
Да. Если тебе нужно определённое число знаков после запятой, то пользуйся (rtos).