开发者

Curious behavior of Access.Application.Eval()

Explain why Access.Application.Eval() (commonly abbreviated as Eval()) produces a different result than just evaluating the original expression in this case:

Debug.Print Round(.57开发者_运维技巧5 * 100)
 57 
Debug.Print Eval("Round(.575 * 100)")
 58 

EDIT: To address GSerg's answer, the following still returns different results:

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


That multiplication returns a different product under Eval(), but I don't understand why.

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

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

In the first case, the product is less than 57.5, so Round() will round it down to 57.

In the second case, the product is equal to 57.5, so Round() will apply its standard "round to even" approach to yield 58.

Edit: You all are right that Eval() coerces the literal value to a different data type.

? TypeName(.575)
Double

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

? Round(CDec(.575) * 100)
 58


That is because of different float precision.

In one case the constants get recognized as Doubles, in the other as Singles.

? math.round((.575! - Int(.575!)) * 100)
 58 
? math.round((.575# - Int(.575#)) * 100)
 57 


GSerg got me thinking. I'm starting to believe that Jet attempts to coerce decimal literals to the Currency type when Eval is called whereas VBA coerces decimal literals to the Double type. Case in point:

? 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 


I don't use Access, but I would guess that the Eval evaluates the expression as an Access expression, so that the Round and Int functions may operate differently from the VBA versions?

I know from bitter experience that VBA's Round() function uses the round-to-even rounding method (aka Banker's rounding), rather than the more common round-away-from-zero-on-a-5 (aka symmetric arithmetic rounding) method.


If you run the following SQL expression in Access, you get 58:

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

If you run the following statement in Access (and, for that matter any Office VBA IDE) Immediate window, you get 57:

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

So, that leads me to believe VBA has a different way of doing Round rather than Access and, probably more applicable, JET.

Now, why is that different? Dunno...will take someone with better skills than me.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜