Статья Даниеля Пино -
VBA - Остерегайтесь ошибок в вычислениях (функция int()) https://www.devhut.net/2019/04/11/vba-beware-of-flawed-math/Я решил, что расскажу об ошибке, доведенной до моего сведения
Джейсоном, касающуюся проблемы с использованием функции
Int() .
Всегда были проблемы с вычислениями из-за проблем с плавающей запятой, о которых я даже не собираюсь рассказывать в этом посте. Есть гораздо большие умы, которые разрабатывали эту тему в прошлом. Тем не менее, всякий раз, когда вам нужно выполнить какой-либо расчет, лучше всего всегда использовать денежные или десятичные типы данных.
Возвращаясь к сегодняшнему сообщению, проблема с функцией Int(). Int () используется для возврата целой части числа из числа. Так,
? Int (1)
1
? Int (5.25)
5
? Int (13.65)
13
Недостаток!В Access Query
В запросе
SELECT 40*0.3 AS Expr1, Int(12) AS Expr2, Int(40*0.3) AS Expr3;
Результаты в
12 | 12 | 12
В рабочем листе Excel= INT(40 * 0,3)
Результаты в
12
НО В VBA (ошибка)? 40 * 0,3
12
? INT(12)
12
но возникает проблема с
? int(40 * .3)
11
или в простой функции, как
Function dd(a As Integer, b As Double)
dd = Int(a * b)
End Function
? dd(40, 0.3)
11
Теперь, поскольку в VBA существует такая проблема, это означает, что это общая ошибка Office VBA, а не только Access! Так что будьте предупреждены, та же проблема будет существовать в Excel, Word, ...
Где это зацепит нас точноТеперь, когда, очевидно, на базовую математическую функцию, такую, как
Int(), нельзя положиться, что делать ?!
Что ж, я опубликовал эту проблему в
Access Dev Team и пока не получил ответа, но, как обычно, мои коллеги из MVP готовы предложить свою помощь!
Густав Брок указал, что использование функции преобразования заставит
Int() вести себя правильно. Таким образом, обходной путь становится
? Int(CDec(40) * 0,3)
12
или же
? Int(40 * CCur(0,3))
12
Итак, да, вам нужно применять преобразование везде, где вы используете Int(), чтобы убедиться, что оно работает правильно!
В случае функции переключение типа данных с Double на Currency устранит проблему
Function dd(a As Integer, b As Currency)
dd = Int (a * b)
End Function
? dd (40, 0,3)
12
или применить преобразование в самой функции, такой как
Function dd(a As Integer, b As Currency)
dd = Int(a * b)
End Function
? 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-ти миллиардное состояние Билла Гейтса?
https://www.sql.ru/forum/1314829/vba-osteregaytes-oshibok-v-vychisleniyah-funkciya-int