问题描述
今天,我遇到了ColdFusion 9,10,11的意外行为或知识不足,这是我的情景
Today I come across unexpected behavior or lack of knowledge with ColdFusion 9,10,11 Round function here is my scenario
Round(28.5)--->预期结果为29
舍入(0.285 * 100)--->预期结果为28
Round(precisionEvaluate(0.285 * 100))--->使用precisionEvaluate结果为29!
Round(Evaluate(0.285 * 100))--->使用Evaluate结果为29!
这不是小数点,为什么我需要对数字使用precisionEvaluate或Evaluate?
在进一步的研究中,我发现了更多有趣的行为
Round(0.285 * 100)的结果是28-为什么?我希望29--!
四舍五入(0.295 * 100)的结果是30 ----正确!
四舍五入(0.275 * 100)的结果是28 ----对!
四舍五入(0.185 * 100)的结果是19 ----对!
四舍五入(0.385 * 100)的结果是39 ----对!
Round(28.5) ---> result is 29 expected
Round(0.285*100) ---> result is 28 not expected
Round(precisionEvaluate(0.285*100)) ---> result is 29 using precisionEvaluate!
Round(Evaluate(0.285*100)) ---> result is 29 using Evaluate!
This is not big decimal, why I would need to use precisionEvaluate or Evaluate on a number?
On farther research I found more interesting behavior
Round(0.285*100) result is 28 --WHY? I'm expecting 29-- !
Round(0.295*100) result is 30 ---- Correct !
Round(0.275*100) result is 28 ---- Correct !
Round(0.185*100) result is 19 ---- Correct !
Round(0.385*100) result is 39 ---- Correct !
推荐答案
这不是十进制数字的精度,而是底层浮点数在Java中的存储方式.这表明:
It's not the precision of the decimal numbers, it's how the underlying floats are stored in Java. This demonstrates:
<cfoutput>
<cfloop array="#[0.275,0.285,0.295]#" index="s">
#s.getClass().getName()#
<cfset f1 = s + 0>
#f1.getClass().getName()#
#f1.toString()#
<cfset f2 = f1*100>
#f2.toString()#
#round(f2)#<br>
</cfloop>
</cfoutput>
输出:
java.lang.String java.lang.Double 0.285 28.499999999999996 28
java.lang.String java.lang.Double 0.285 28.499999999999996 28
java.lang.String java.lang.Double 0.295 29.5 30
java.lang.String java.lang.Double 0.295 29.5 30
我只能假设在执行<cfset f1 = s + 0>
时从字符串转换为浮点数时CF使用更好的精度,因为那里没有躲避的四舍五入.但是,执行完乘法步骤后,我们得到了准确度错误.28.5最终仅差28.5,因此四舍五入为28,而不是29.这只是二进制小数算法问题.
I can only assume under the hood CF uses better precision when converting from a string to a float when performing <cfset f1 = s + 0>
as there's no dodgy rounding there. However having performed the multiplication step we're getting an accuracy error bleeding in. 28.5 ends up being just shy of 28.5, so rounds to 28 not 29. It's just a binary fraction arithmetic issue.
顺便说一句,0.285没什么特别的.许多数字也会受到类似的影响(请查看0.005到5.05之间的范围).您只是碰巧捡到了一大堆(不是0.285).
BTW, there's nothing special about 0.285. A lot of numbers are similarly effected (have a look at the range from 0.005 to 5.05). You just happened to pick a bunch that aren't (other than 0.285).
这篇关于ColdFusion Round函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!