Страницы: 1 2 След.
RSS
Получаю разное значение при одинаковых условиях в функциях Int и Fix
 
Доброго дня. Подскажите пожалуйста, почему получается разные результаты, если в первом примере число функции 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

Изменено: Shama - 09.09.2021 08:48:17
Не перестаю удивляться возможностям excel и VBA.
 
Особенность функций. Если вызываете их без указания родителя, то работают несколько иначе. Запишите так:
Код
VBA.Fix(x * 10000)
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Интересный глюк.
Причем, если задать тип данных Variant, то срабатывает правильно.
 
кстати прикольно что
Fix(cdbl(1.1234 * 10000)) = 11234
а
Fix(1.1234 * 10000) = 11233

vba.Fix дает 11234 всегда
По вопросам из тем форума, личку не читаю.
 
Дмитрий(The_Prist) Щербаков, Спасибо, работает. Учту на будущее такой метод, вероятно еще пригодится.
RAN, Действительно, даже не думал, что изменения типа на Variant повлияет на результат.
БМВ, предполагал, что Cdbl работает аналогично второму варианту, но здорово уменьшает код, спасибо.
Спасибо за ответы, но кажется вопросов стало только больше)
Изменено: Shama - 09.09.2021 09:35:57
Не перестаю удивляться возможностям excel и VBA.
 
Тут вопрос реализации. Fix(без VBA) работает чуть иначе. На мой взгляд VBA.Fix чуть лучше и грамотнее. Без VBA Fix производит попытку приведения к типу каждого значения в выражении(независимо от того, делаем это мы ранее или нет), что приводит к "хвостам". Т.е. еще ДО вычисления самой функции Fix число уже "портится" вследствие этих преобразований. Попробуйте вычислить такое выражение:
Код
fix(1.1234*10000000000000)
и все станет ясно. VBA.Fix все преобразования делает сама.
Изменено: Дмитрий(The_Prist) Щербаков - 09.09.2021 09:55:15
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
На 100 млн VBA.Fix ничтожно, но проигрывает: 3,8 сек против 2,4 сек
я думал, что все функции VBA без указания родителя, это и есть VBA.Function()…  :sceptic:
Спасибо!  :idea:
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Дмитрий(The_Prist) Щербаков, Логика понятна, хоть и не привычна. Привык что функция работает с уже рассчитанным значением.
Но почему тогда эти примеры не портятся до расчета функции?
Fix(0.1 * 2 + 1.9)
Fix(0.25 * 4)
Fix(0.25 + 0.25 + 0.25 + 0.25)
Не перестаю удивляться возможностям excel и VBA.
 
Цитата
Shama: почему тогда эти примеры не портятся до расчета функции?
особенности двоичной арифметики, чтоб её  :)
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Shama написал:
почему тогда эти примеры не портятся
Цитата
Jack Famous написал:
особенности двоичной арифметики
именно.
Даже в Excel выделите ячейки А1:А2 -Формат ячеек -Числовой - 15 знаков после запятой.
В А1 введите формулу:
Код
=10,2-10,1
а в А2 такую:
Код
=10,3-10,2
и посмотрите на последний знак после запятой...
Изменено: Дмитрий(The_Prist) Щербаков - 09.09.2021 10:23:55
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
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 то результат уже НЕ РАВЕН СЕКУНДЕ!!!
потому что компьютер именно так СМОГ сохранить это число в памяти и НИКАК по другому. никак...
Изменено: Ігор Гончаренко - 09.09.2021 10:43:13
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Дмитрий(The_Prist) Щербаков написал:
VBA.Fix чуть лучше и грамотнее.
или корректнее, что-то мне кажется кто-то, когда-то напахал и это так и тянется. VBS отрабатывает корректно в любом варианте.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
кто-то, когда-то напахал
именно. Потому что Fix без VBA опирается еще и на Excel, а Fix в VBS к Excel никакого отношения не имеет(он самостоятелен) и ему просто нет вариантов к нему сослаться :)
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
А есть еще подобные функции?
 
и что по поводу
Цитата
Jack Famous: я думал, что все функции VBA без указания родителя, это и есть VBA.Function()
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
а в данной теме как и во многих других нужно писать не
Цитата
Shama написал:
Получаю разное значение при одинаковых условиях в функциях Int и Fix
потому что  Int и Fix выдают разные результаты ТОЛЬКО при работе с отрицательными десятичными числами и это описано в документации

а нужно писать какую задачу решаете (что не получилось, к какому парадоксальному результату пришли) и тогда получите подсказку как это решить, а не эти "загадочные" примеры, которые являются загадкой только для начинающих пользователей и давно известны для многих и учитываются там где это нужно учесть
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Ігор Гончаренко написал:
которые являются загадкой только для начинающих пользователей
Не скажи...
Я, вроде, не совсем начинающий, но столкнулся впервые.
 
RAN,
да ну! это одно и тоже раз в несколько месяцев у кого возникает очередная загадка "как так?"
пройдет пару месяцев а может и не пройдет и мы снова прочитаем почема А + В - А <> B, потому что проверяйте это равенство с определенной точность и будьте счастливы!

см.сообщение 11, файл "секунда"
без всяких Фикс Инт и пр.
в 86 строке оказалось, что  Какое-тоВремя + 1Секунда  - Какое-тоВремя НЕ РАВНО 1Секунда
с точки зрения математики - полный бред, с точки зрения способа хранения данных в памяти компьютера - ситуация описана, учитывайте там где это нужно и можете не обращать внимания во всех остальных случаях
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Я говорю не про стандарт вычислений, а про VBA.Fix.
 
Ігор Гончаренко, ты не прав в данном случае, я соглашусь что
Цитата
Ігор Гончаренко написал:
Int и Fix выдают разные результаты ТОЛЬКО при работе с отрицательными десятичными числами и это описано в документации
о чем и спрашивает название темы, но все ж вопрос в другом. Вс еж разница именно в результате функции при аргументе полученном вычисляемым выражением или переменной, которая хранит результат вычисления того же выражения.
По вопросам из тем форума, личку не читаю.
 
Дмитрий(The_Prist) Щербаков, Ігор Гончаренко, Благодарю, доходчиво объяснили.
Цитата
Ігор Гончаренко написал:
сколько раз объяснялось это особенности хранения в памяти компьютера десятичных чисел
Честно не знал. Но не уверен, что не наступлю на те же "грабли" в будущем.

Цитата
Ігор Гончаренко написал:
Shama  написал:Получаю разное значение при одинаковых условиях в функциях Int и Fix
Соглашусь, звучит двояко. Однако подробно описал проблему в теме.
Не перестаю удивляться возможностям excel и VBA.
 
Цитата
БМВ написал:
кстати прикольно чтоFix(cdbl(1.1234 * 10000)) = 11234  а   Fix(1.1234 * 10000) = 11233
А вот интересно, что примеры, аналогичные, ниже дают одинаковый результат. Получается преобразование cdbl() не работает? (Конечно, уже определились что лучше будет через VBA.)
Fix(66.1402 * 10000)
Fix(CDbl(66.1402 * 10000))
Изменено: Shama - 09.09.2021 11:55:39
Не перестаю удивляться возможностям excel и VBA.
 
Цитата
RAN: Я говорю про VBA.Fix
поддерживаю - первый раз столкнулся и крайне удивлён  :idea:
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
для новый идей:
Код
Sub test1()
  Dim x As Double, s$, i
  Debug.Print Fix(1.1 * 10)
  Debug.Print Fix(1.11 * 100)
  Debug.Print Fix(1.111 * 1000)
  Debug.Print Fix(1.1111 * 10000)
  Debug.Print Fix(1.11111 * 100000)
  Debug.Print Fix(1.111111 * 1000000)
  Debug.Print Fix(1.1111111 * 10000000)
  Debug.Print Fix(1.11111111 * 100000000)
  Debug.Print Fix(1.111111111 * 1000000000)
End Sub
рдавайте решим это Fix кривой или как?
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
В очередной раз напоминаю вам, друзья мои, что мы находимся в мире приближенных вычислений, в котором нет понятия равенства для дробных чисел (если только их знаменатели не являются степенью двойки).
Число 1.1234 является бесконечной периодической дробью в двоичной системе счисления и в формате double будет округлено с минимально возможной (но не нулевой) погрешностью. После умножения на 10000 погрешность увеличится в 10000 раз. При этом результат может отклониться от точного значения (11234) как в большую, так и в меньшую сторону. Если отклонится в меньшую сторону, то Fix вернет 11233.

Что здесь удивительного?
Изменено: sokol92 - 09.09.2021 14:12:47
Владимир
 
sokol92, приветствую, Владимир!
Цитата
sokol92: Что здесь удивительного?
кажется, вы тоже не поняли… Приколы двоичной арифметики я знаю и отметил
Цитата
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 - 09.09.2021 14:24:07
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
почему результаты функций Fix() и VBA.Fix() — отличаются
потому что это две разные реализации одной функции
отличаются всегда или на некоторых значениях?
Цитата
Jack Famous написал:
Приколы двоичной арифметики я знаю и отметил
знаете - это отлично осталось научиться пользоваться
из старого анекдота:
-- ты в качалку ходишь?
-- хожу
-- а чего не качаешься?
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Jack Famous написал:
почему результаты функций Fix() и VBA.Fix() — отличаются при одинаковых аргументах?
Какие-то особенности компилятора. Без анализа исходного кода ничего нельзя сказать. Я бы не стал на этом зацикливаться, потому что оба варианта ответа (11233 и 11234) равно приемлемы.
Посмотрел на

Код
Debug.Print Fix(1.1234 * 10000)

в Word. Там у меня (Word 2016 32- Win10) другая ситуация: первый раз выдается 11234, а далее - 11233.
Изменено: sokol92 - 09.09.2021 14:57:49
Владимир
 
Цитата
sokol92: оба варианта ответа (11233 и 11234) равно приемлемы
не соглашусь, поскольку 1.1234 * 10000 — это 11 234 и никак иначе (особенно учитывая, что само выражение вычисляется правильно)
Если для получения верного результата нужно вызывать функцию через родителя, то, значит, так тому и быть  :)
Спасибо!  ;)
Изменено: Jack Famous - 09.09.2021 14:57:59
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
1.1234 * 10000 — это 11 234 и никак иначе
Для Excel и других подобных программ  - см. #25.
Владимир
Страницы: 1 2 След.
Наверх