Доброго дня. Подскажите пожалуйста, почему получается разные результаты, если в первом примере число функции Fix задано расчетом, а во втором рассчитанной переменной? Аналогично ведет себя int. Fix((1.1234 * 10000)) = 11233, почему? Грубо говоря это проверка числа на округление до 4 знака после запятой.
Код
Sub test1()
Dim x As Double
x = 1.1234
If (x * 10000) - Fix((x * 10000)) <> 0 Then MsgBox "Ошибка"
End Sub
Sub test2()
Dim x As Double, y As Double
x = 1.1234
y = x * 10000
If y - Fix(y) <> 0 Then MsgBox "Ошибка"
End Sub
Дмитрий(The_Prist) Щербаков, Спасибо, работает. Учту на будущее такой метод, вероятно еще пригодится. RAN, Действительно, даже не думал, что изменения типа на Variant повлияет на результат. БМВ, предполагал, что Cdbl работает аналогично второму варианту, но здорово уменьшает код, спасибо. Спасибо за ответы, но кажется вопросов стало только больше)
Тут вопрос реализации. Fix(без VBA) работает чуть иначе. На мой взгляд VBA.Fix чуть лучше и грамотнее. Без VBA Fix производит попытку приведения к типу каждого значения в выражении(независимо от того, делаем это мы ранее или нет), что приводит к "хвостам". Т.е. еще ДО вычисления самой функции Fix число уже "портится" вследствие этих преобразований. Попробуйте вычислить такое выражение:
Код
fix(1.1234*10000000000000)
и все станет ясно. VBA.Fix все преобразования делает сама.
На 100 млн VBA.Fix ничтожно, но проигрывает: 3,8 сек против 2,4 сек
я думал, что все функции VBA без указания родителя, это и есть VBA.Function()… Спасибо!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Дмитрий(The_Prist) Щербаков, Логика понятна, хоть и не привычна. Привык что функция работает с уже рассчитанным значением. Но почему тогда эти примеры не портятся до расчета функции? Fix(0.1 * 2 + 1.9) Fix(0.25 * 4) Fix(0.25 + 0.25 + 0.25 + 0.25)
Shama: почему тогда эти примеры не портятся до расчета функции?
особенности двоичной арифметики, чтоб её
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Shama написал: но кажется вопросов стало только больше)
с чего бы? сколько раз обьяснялось это особенности хранения в памяти компьютера десятичных чисел см. файл пример в А1 я написал 00:00:01 и назвал эту ячейку секунда в А2 = А1+секунда и видно 00:00:02 в В2 написано =А2-А1=секунда и видно результат ИСТИНА,, "а как иначе?" - можете подумать вы А2 получено как А1 + секунда соотв. вопрос (А2-А1) =секунда? должен дать положительный ответ, да А2-А1 = секунда!
я отметил А2 и В2 и потянул ячейки с этими формулами вниз все шло хорошо до 85 строки, а в 86-й строке оказалось что если к минута 25 прибавить 1 секунду будет минута 26 (видно) а если от минуты 26 отнять минуту 25 то результат уже НЕ РАВЕН СЕКУНДЕ!!! потому что компьютер именно так СМОГ сохранить это число в памяти и НИКАК по другому. никак...
именно. Потому что Fix без VBA опирается еще и на Excel, а Fix в VBS к Excel никакого отношения не имеет(он самостоятелен) и ему просто нет вариантов к нему сослаться
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
Jack Famous: я думал, что все функции VBA без указания родителя, это и есть VBA.Function()
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
а в данной теме как и во многих других нужно писать не
Цитата
Shama написал: Получаю разное значение при одинаковых условиях в функциях Int и Fix
потому что Int и Fix выдают разные результаты ТОЛЬКО при работе с отрицательными десятичными числами и это описано в документации
а нужно писать какую задачу решаете (что не получилось, к какому парадоксальному результату пришли) и тогда получите подсказку как это решить, а не эти "загадочные" примеры, которые являются загадкой только для начинающих пользователей и давно известны для многих и учитываются там где это нужно учесть
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
RAN, да ну! это одно и тоже раз в несколько месяцев у кого возникает очередная загадка "как так?" пройдет пару месяцев а может и не пройдет и мы снова прочитаем почема А + В - А <> B, потому что проверяйте это равенство с определенной точность и будьте счастливы!
см.сообщение 11, файл "секунда" без всяких Фикс Инт и пр. в 86 строке оказалось, что Какое-тоВремя + 1Секунда - Какое-тоВремя НЕ РАВНО 1Секунда с точки зрения математики - полный бред, с точки зрения способа хранения данных в памяти компьютера - ситуация описана, учитывайте там где это нужно и можете не обращать внимания во всех остальных случаях
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
Ігор Гончаренко, ты не прав в данном случае, я соглашусь что
Цитата
Ігор Гончаренко написал: Int и Fix выдают разные результаты ТОЛЬКО при работе с отрицательными десятичными числами и это описано в документации
о чем и спрашивает название темы, но все ж вопрос в другом. Вс еж разница именно в результате функции при аргументе полученном вычисляемым выражением или переменной, которая хранит результат вычисления того же выражения.
А вот интересно, что примеры, аналогичные, ниже дают одинаковый результат. Получается преобразование cdbl() не работает? (Конечно, уже определились что лучше будет через VBA.) Fix(66.1402 * 10000) Fix(CDbl(66.1402 * 10000))
поддерживаю - первый раз столкнулся и крайне удивлён
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
В очередной раз напоминаю вам, друзья мои, что мы находимся в мире приближенных вычислений, в котором нет понятия равенства для дробных чисел (если только их знаменатели не являются степенью двойки). Число 1.1234 является бесконечной периодической дробью в двоичной системе счисления и в формате double будет округлено с минимально возможной (но не нулевой) погрешностью. После умножения на 10000 погрешность увеличится в 10000 раз. При этом результат может отклониться от точного значения (11234) как в большую, так и в меньшую сторону. Если отклонится в меньшую сторону, то Fix вернет 11233.
кажется, вы тоже не поняли… Приколы двоичной арифметики я знаю и отметил
Цитата
Jack Famous: особенности двоичной арифметики, чтоб её
Лично у меня вопрос был, почему результаты функций Fix() и VBA.Fix() — отличаются при одинаковых аргументах? Я всегда думал, что все функции VBA это тоже самое, что VBA.Func() — ведь даже Definition отсылает к одинаковым пунктам справки, а именно
Код
Function Fix(Number) → Member of VBA.Conversion
В принципе Дима ответил
Цитата
Дмитрий(The_Prist) Щербаков: Потому что Fix без VBA опирается еще и на Excel, а Fix в VBS к Excel никакого отношения не имеет(он самостоятелен) и ему просто нет вариантов к нему сослаться
и это объясняет в чём, но не объясняет, почему и сколько функций VBA могут также давать разные ответы при обращении Func() / VBA.Func()
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Jack Famous написал: почему результаты функций Fix() и VBA.Fix() — отличаются при одинаковых аргументах?
Какие-то особенности компилятора. Без анализа исходного кода ничего нельзя сказать. Я бы не стал на этом зацикливаться, потому что оба варианта ответа (11233 и 11234) равно приемлемы. Посмотрел на
Код
Debug.Print Fix(1.1234 * 10000)
в Word. Там у меня (Word 2016 32- Win10) другая ситуация: первый раз выдается 11234, а далее - 11233.
sokol92: оба варианта ответа (11233 и 11234) равно приемлемы
не соглашусь, поскольку 1.1234 * 10000 — это 11 234 и никак иначе (особенно учитывая, что само выражение вычисляется правильно) Если для получения верного результата нужно вызывать функцию через родителя, то, значит, так тому и быть Спасибо!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄