Любопытное поведение Access.Application.Eval () - PullRequest
8 голосов
/ 22 июня 2011

Объясните, почему Access.Application.Eval() (обычно сокращенно Eval()) дает другой результат, чем просто оценка исходного выражения в этом случае:

Debug.Print Round(.575 * 100)
 57 
Debug.Print Eval("Round(.575 * 100)")
 58 

РЕДАКТИРОВАТЬ: Чтобы ответить на ответ GSerg, следующее по-прежнему возвращает разные результаты:

Debug.Print Eval("Round(CSng(.575) * 100)")
 57 
Debug.Print Round(CSng(.575) * 100)
 58 

Ответы [ 5 ]

6 голосов
/ 22 июня 2011

Это умножение возвращает другой продукт в Eval (), но я не понимаю, почему.

Debug.Print (.575 * 100) < 57.5
True

Debug.Print Eval("(.575 * 100) = 57.5")
-1

В первом случае продукт меньше 57,5, поэтому Round () будет округлять егодо 57.

Во втором случае произведение равно 57,5, поэтому Round () применит свой стандартный подход "округлить до четного", чтобы получить 58.

Править: Вы все правы, что Eval () приводит буквальное значение к другому типу данных.

? TypeName(.575)
Double

? Eval("TypeName(.575)")
Decimal

? Round(CDec(.575) * 100)
 58
4 голосов
/ 22 июня 2011

Это из-за разной точности вычислений.

В одном случае константы распознаются как Double с, в другом - Single с.

? math.round((.575! - Int(.575!)) * 100)
 58 
? math.round((.575# - Int(.575#)) * 100)
 57 
2 голосов
/ 22 июня 2011

GSerg заставил меня задуматься.Я начинаю верить, что Jet пытается привести десятичные литералы к типу Currency при вызове Eval, тогда как VBA приводит десятичные литералы к типу Double.Показательный пример:

? Math.Round(.575 * 100)
 57 
? Math.Round(CSng(.575) * 100)
 58 
? Math.Round(CDbl(.575) * 100)
 57 
? Math.Round(CCur(.575) * 100)
 58 

? Eval("Round(.575 * 100)")
 58 
? Eval("Round(CSng(.575) * 100)")
 57 
? Eval("Round(CDbl(.575) * 100)")
 57 
? Eval("Round(CCur(.575) * 100)")
 58 
1 голос
/ 22 июня 2011

Я не использую Access, но я предполагаю, что Eval оценивает выражение как выражение Access, так что функции Round и Int могут работать иначе, чем версии VBA?

По горькому опыту я знаю, что функция Round () в VBA использует метод округления до четного (округление по Банкеру), а не более распространенный метод округления до нуля на 5 (он же симметричный). арифметическое округление) метод.

0 голосов
/ 22 июня 2011

Если вы запустите следующее выражение SQL в Access, вы получите 58:

select Round((.575 - Int(.575)) * 100) as MyValue

Если вы запустите следующий оператор в Access (и, в этом отношении, для любой среды Office VBA IDE), вы получите57:

Round((.575 - Int(.575)) * 100)

Итак, это наводит меня на мысль, что VBA имеет другой способ выполнения Round, а не Access и, возможно, более применимый, JET.

Теперь, почему отличается от ?Не знаю ... возьму кого-нибудь с лучшими навыками, чем я.

...