VBA: странное поведение с функцией Int

Мне интересно такое поведение, которое я вижу в VBA. Я использую консоль Immediate для отладки своего кода и получил следующий результат:

Debug.Print(Int(0.00024575*10000000+0.5))
 2457

Я ожидал, что этот результат будет 2458. Кто-нибудь знает, почему это происходит? Как и ожидалось, перед вызовом функции Int вычисления производятся с двойной точностью.

Debug.Print(VarType(0.00024575*10000000+0.5))
 5 

Любая помощь очень ценится!

Я предполагаю ошибку с плавающей запятой.

BigBen 31.07.2024 17:29

Но разве не следует Int правильно обращаться с двойниками? Это плохое поведение для такого широко используемого языка, как VBA.

Atreyu 31.07.2024 17:38

Вместо этого попробуйте использовать CInt. Он будет округлять, а не усекать результат. Согласно файлу справки: «Когда дробная часть равна ровно 0,5, CInt и CLng всегда округляют ее до ближайшего четного числа. Например, 0,5 округляет до 0, а 1,5 округляет до 2. CInt и CLng отличаются от функций Fix и Int, которые усекают, а не округляют дробную часть числа. Кроме того, Fix и Int всегда возвращают значение того же типа, что и передано.

Brian M Stafford 31.07.2024 17:39

@BigBen Извините, я просто имел в виду, что это удивительное поведение, даже для функции, которая просто усекает. Я бы подумал, что это даст более надежный результат, но он кажется не очень надежным... Я ожидаю ошибок с плавающей запятой при более высокой точности ввода.

Atreyu 31.07.2024 17:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
4
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы запустите следующий тест:

Sub Test()
    Dim d As Double: d = 0.5 + 0.00024575 * 10000000
    
    Debug.Assert d = Int(d)
    Debug.Assert 0.5 + 2457.5 = Int(0.5 + 2457.5)
    Debug.Assert 0.5 + 0.00024575 * 10000000 = Int(CDbl(0.5 + 0.00024575 * 10000000))
    Debug.Assert 0.5 + 0.00024575 * 10000000 = CDbl(0.5 + 0.00024575 * 10000000)
    Debug.Assert 0.5 + 0.00024575 * 10000000 = VBA.Int(0.5 + 0.00024575 * 10000000)
    Debug.Assert 0.5 + 0.00024575 * 10000000 = Int(0.5 + 0.00024575 * 10000000)
End Sub

Вы увидите, что только последний Assert не работает. Вероятно, это ошибка компилятора.

Обратите внимание, что Int — это не то же самое, что VBA.Int.

Редактировать №1

Как было предложено в комментариях @GSerg, похоже, что метод Int (не VBA.Int) действительно выполняет вычисления во время компиляции и, вероятно, использует другую точность с плавающей запятой. Например:

Option Explicit

#Const Test = Int(12.5)

Sub TestPrecompiler()
    #If Test = 12 Then
        Debug.Print "Int method calculates at compile time"
    #End If
End Sub

Очень интересно, хорошая находка.

BigBen 31.07.2024 18:16

Значит, Int тоже забавная функция , как у Лена ? Но это не ключевое слово , и я не вижу для этого причин. Это как если бы весь Int(0.5 + 0.00024575 * 10000000) вычислялся во время компиляции (что может быть и в случае забавных функций), и в этот момент компилятор использовал различную точность с плавающей запятой (что не является чем-то необычным), в то время как все остальное обрабатывается во время выполнения.

GSerg 31.07.2024 18:49

@GSerg Действительно. Если я правильно помню, Int можно использовать в константах компилятора, но я не могу проверить это.

Cristian Buse 31.07.2024 18:53

Нет, говорит: Требуется постоянное выражение.

GSerg 31.07.2024 18:55

@GSerg хорошие рефералы, спасибо!

Atreyu 31.07.2024 19:37

@GSerg #Const Test = Int(12.5) у меня компилируется нормально. Я использую Office 365 Excel на Win x64 VBA7.

Cristian Buse 01.08.2024 09:57

Так что это работает в константе компиляции. Однако в обычных константах этого нет. И потом Int не является чем-то особенным, многие другие тоже работают в константах компиляции, но не в обычных.

GSerg 01.08.2024 10:26

Другие вопросы по теме