今天我遇到了意外行为或对 ColdFusion 9,10,11 Round 函数缺乏了解,这是我的场景
Round(28.5) ---> 预期结果为 29
Round(0.285*100) ---> 结果不是预期的 28
Round(precisionEvaluate(0.285*100)) ---> 结果是 29 使用 precisionEvaluate!
Round(Evaluate(0.285*100)) ---> 使用 Evaluate 的结果是 29!
这不是大十进制,为什么我需要对数字使用 precisionEvaluate 或 Evaluate?
在进一步的研究中,我发现了更有趣的行为
Round(0.285*100) 结果是 28 --为什么?我期待 29--!
Round(0.295*100) 结果是 30 ---- 正确!
Round(0.275*100) 结果是 28 ---- 正确!
Round(0.185*100) 结果是 19 ---- 正确!
Round(0.385*100) 结果是 39 ---- 正确!
0.285*100 有什么大不了的?
最佳答案
这不是十进制数的精度,而是底层浮点数在 Java 中的存储方式。这表明:
<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.275 27.500000000000004 28
java.lang.String java.lang.Double 0.285 28.499999999999996 28
java.lang.String java.lang.Double 0.295 29.5 30
我只能假设在幕后 CF 在执行
<cfset f1 = s + 0>
时从字符串转换为浮点数时使用更好的精度因为那里没有狡猾的四舍五入。然而,在执行乘法步骤后,我们得到了准确度错误。28.5 最终接近 28.5,所以四舍五入到 28 而不是 29。这只是一个二进制分数算术问题。顺便说一句,0.285 没有什么特别之处。许多数字受到类似的影响(看看从 0.005 到 5.05 的范围)。你只是碰巧选择了一堆不是(除了 0.285)。
关于math - ColdFusion 圆函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27494253/