powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / VBA - Остерегайтесь ошибок в вычислениях (функция int())
9 сообщений из 9, страница 1 из 1
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837760
Фотография Joss
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Статья Даниеля Пино - VBA - Остерегайтесь ошибок в вычислениях (функция int())

https://www.devhut.net/2019/04/11/vba-beware-of-flawed-math/

Я решил, что расскажу об ошибке, доведенной до моего сведения Джейсоном , касающуюся проблемы с использованием функции Int() .

Всегда были проблемы с вычислениями из-за проблем с плавающей запятой, о которых я даже не собираюсь рассказывать в этом посте. Есть гораздо большие умы, которые разрабатывали эту тему в прошлом. Тем не менее, всякий раз, когда вам нужно выполнить какой-либо расчет, лучше всего всегда использовать денежные или десятичные типы данных.

Возвращаясь к сегодняшнему сообщению, проблема с функцией Int(). Int () используется для возврата целой части числа из числа. Так,

Код: plaintext
1.
2.
3.
4.
5.
? Int (1)
 1 
? Int (5.25)
 5 
? Int (13.65)
 13

Недостаток!

В Access Query
В запросе
Код: sql
1.
SELECT 40*0.3 AS Expr1, Int(12) AS Expr2, Int(40*0.3) AS Expr3;


Результаты в
Код: plaintext
12 | 12 | 12

В рабочем листе Excel
Код: plaintext
= INT(40 * 0,3) 
Результаты в
Код: plaintext
12

НО В VBA (ошибка)

Код: plaintext
1.
2.
3.
? 40 * 0,3
12 
? INT(12)
12

но возникает проблема с

Код: plaintext
1.
? int(40 * .3)
 11

или в простой функции, как

Код: vbnet
1.
2.
3.
Function dd(a As Integer, b As Double)
    dd = Int(a * b)
End Function


Код: plaintext
1.
? dd(40, 0.3)
11

Теперь, поскольку в VBA существует такая проблема, это означает, что это общая ошибка Office VBA, а не только Access! Так что будьте предупреждены, та же проблема будет существовать в Excel, Word, ...

Где это зацепит нас точно

Теперь, когда, очевидно, на базовую математическую функцию, такую, как Int() , нельзя положиться, что делать ?!

Что ж, я опубликовал эту проблему в Access Dev Team и пока не получил ответа, но, как обычно, мои коллеги из MVP готовы предложить свою помощь! Густав Брок указал, что использование функции преобразования заставит Int() вести себя правильно. Таким образом, обходной путь становится

Код: plaintext
1.
? Int(CDec(40) * 0,3)
12

или же

Код: plaintext
1.
? Int(40 * CCur(0,3))
12

Итак, да, вам нужно применять преобразование везде, где вы используете Int(), чтобы убедиться, что оно работает правильно!

В случае функции переключение типа данных с Double на Currency устранит проблему

Код: vbnet
1.
2.
3.
Function dd(a As Integer, b As Currency)
    dd = Int (a * b)
End Function


Код: plaintext
1.
? dd (40, 0,3)
12
или применить преобразование в самой функции, такой как

Код: vbnet
1.
2.
3.
Function dd(a As Integer, b As Currency)
    dd = Int(a * b)
End Function


Код: plaintext
1.
? dd(40, 0.3)
12

Как всегда, когда я получу ответ от команды Access Dev, я опубликую любую дополнительную информацию, которой они смогут поделиться с нами.

Обновление 2019-04-18, 2019-05-01
Что ж, прошло всего 3 недели, и от команды разработчиков не было никаких комментариев/ответов по поводу моего электронного письма на эту тему, поэтому я полагаю, что не получу от них никаких отзывов по этому вопросу. Так что просто убедитесь, что ВСЕГДА используйте преобразования везде, где вы используете функцию Int(), чтобы избежать каких-либо ошибочных результатов !!!

... и если эта проблема существует в Int(), должны ли мы беспокоиться о других математических функциях? Это настоящий вопрос!

Обновление 2019-04-24
Просто добавлена информация, касающаяся тестирования выше.

Когда я писал статью, я работал под управлением Access 2013 x32 на Windows 7, с тех пор я тестировал (с такими же результатами)

Access 2003 в Windows XP
Access 2007 SP3 (x32) в Windows 7
Access 2010 SP2 (x32) в Windows 7
Access 2013 (x32) в Windows 10 (версия 1803, сборка ОС 17134.706)
Access 2016 (x32) в Windows 7

Дальнейшие ресурсы по теме
В комментариях ниже Люк Чунг , президент FMS Inc. , только что поделился со мной техническим документом, который он выпустил более 20 лет назад, в котором подробно об этом и многом другом! Поэтому не забудьте проверить, When Microsoft Access Math Doesn’t Add Up , чтобы убедиться, что вы знаете о множестве математических проблем и о том, как наилучшим образом обеспечить надежность ваших расчетов.


-------------------------------------------------------------
А ты вложил уже свой кровный рубль в 50-ти миллиардное состояние Билла Гейтса?
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837787
Фотография Панург
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Joss, я так понимаю, что этот Даниель Пино вчера вылупился?
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837795
Это именно "из-за проблем с плавающей запятой". Некоторые десятичные числа невозможно представить в двоичной системе со 100% точностью. Например 0.3 может выглядеть как 0.299999999999, поэтому:
Код: vbnet
1.
2.
?40*0.299999999999
 11.99999999996

А Int() честно отбрасывает дробную часть и возвращает 11.
Для наглядности?
Код: vbnet
1.
2.
3.
4.
?Int(40000000000*0.3)
 11999999999 
?Int(40000000000*0.6)
 23999999999


В данном случае 0.3 имеет тип Double (в VBA по умолчанию для дробных чисел).

Что интересно, есть тип Single, который еще грубее но здесь:
Код: vbnet
1.
2.
?Int(40000000000*CSng(0.3))
 12000000476
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837813
Фотография sdku
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прежде чем искать ошибку в стандартной функции VBA ("проверенной веками") надо спросить себя:"а все-ли я правильно делаю?" -тип Double,в принципе,не может дать точный результат
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837822
Фотография sdku
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вдогонку:безумно "нравится" когда бестолочь искренне считает себя умней других и пытается оспорить что-то устоявшееся(существует куча доказательств что 2*2=5-кроме смеха и убежденности в том,что автор полный идиёт это не вызывает)
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837823
Фотография Joss
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вчера-не вчера. И о точности то же известно. Но вот можешь нечаянно вляпаться.
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837830
ROI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdkuпрежде чем искать ошибку в стандартной функции VBA ("проверенной веками") надо спросить себя:"а все-ли я правильно делаю?" -тип Double,в принципе,не может дать точный результат
100500
Я ужо думал, что не дождусь этой (правильной реакции)
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837831
Фотография Панург
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JossВчера-не вчера. И о точности то же известно. Но вот можешь нечаянно вляпаться.И что даст это обсуждение? Это описано на сто раз в учебниках по VBA. А уж если придётся встрять, то и сто первый раз не поможет.
...
Рейтинг: 0 / 0
VBA - Остерегайтесь ошибок в вычислениях (функция int())
    #39837870
Фотография sdku
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ПанургJossВчера-не вчера. И о точности то же известно. Но вот можешь нечаянно вляпаться.И что даст это обсуждение? Это описано на сто раз в учебниках по VBA. А уж если придётся встрять, то и сто первый раз не поможет.
+100500
В принципе ничего...
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / VBA - Остерегайтесь ошибок в вычислениях (функция int())
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]