微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ColdFusion 双到长转换错误

如何解决ColdFusion 双到长转换错误

有人可以向我解释为什么 ColdFusion(在 2016、2018 和 2021 年测试过)进行了错误的双到长转换?我知道它可能会弄乱小数值,但在这个例子中,它显然是一个整数值。
这是代码

<cfoutput>
<cfset a = 69.35>
#getMetadata(a)# #a#</br>

<cfset b = a * 100>
#getMetadata(b)# #b#</br>

<cfset c = int(b)>
#getMetadata(c)# #c#</br>
</cfoutput>

这是输出

class coldfusion.runtime.CFDouble 69.35
class java.lang.Double 6935
class java.lang.Long 6934

这样做可以“排序”修复:

<cfset d = int(javacast("string",b))>
#getMetadata(d)# #d#</br>

返回

class java.lang.Long 6935

但我对这个“解决方案”并不满意...... 谢谢!

编辑: 因为 ColdFusion 是在 java 之上运行的,所以我猜这是它的原因:

public static void main(String[] args)
{
  double a = 69.35;
  double b = a * 100;
  System.out.println(b);
  long c = (int)b;
  System.out.println(c);
  long d = Math.round(b);
  System.out.println(d);
}

输出

6934.999999999999
6934
6935

而且最有可能的是,ColdFusion 使用 int() 而不是 round() 将 double 值转换为 long ......这是无类型编程语言的“好”副作用之一,它在内部使它。让我想起了 javascript ;-)

编辑 2:
正如 Cameron 指出的,#b# 和 #b.ToString()# 之间是有区别的。前者返回6935,后者返回6934.999999999999。在我看来,这令人困惑,但我会把它放在我的脑海里,以防我遇到另一个关于 double/long 值的奇怪问题:-)

更让人困惑的是: int(ToString(b)) 返回 6935 而 int(b.ToString()) 返回 6934...

<cfset a = 69.35>
#getMetadata(a)# #a#</br>
<cfset b = a * 100>
#getMetadata(b)# #b#</br>
#b.toString()# #ToString(b)#</br>

回来了:

class java.lang.String 69.35
class java.lang.Double 6935 
6934.999999999999 6935

所以,不要假设 b.ToString() 与 ToString(b) 相同......

解决方法

正如@SOS 在他们的评论中提到的(不知道为什么他们没有把它作为“答案”?),问题不在于转换。问题在于 ColdFusion 将 69.35 * 100 显示为等于 6935,而事实并非如此。甚至 ColdFusion 也不认为是这样。

就大多数计算语言而言,69.35 * 1006934.999999999999(如果您愿意,请检查 JS、Python、Ruby 等),因为在一种以二进制形式存储东西的系统。我以前写过关于这个:Floating point arithmetic with decimals

ColdFusion 在内部将结果存储为 6934.999999999999

<cfset f = 69.35 * 100>
<cfoutput>#f.toString()#</cfoutput>

这产生:

6934.999999999999

因此,当您使用 int6934.999999999999 的整数部分时,您会得到 6934那部分实际上是在正确地完成工作! ;-)

,

我知道我对这个答案有点晚了,但这是我过去在使用货币处理数学计算时遇到 ColdFusion 中的精度问题时使用的方法。为了避免精度错误,我总是用 precisionEvaluate() 函数包装我的数学计算。将它与您的示例代码一起使用

<cfoutput>
<cfset a = 69.35>
#getMetadata(a)# #a#</br>

<cfset b = precisionEvaluate(a * 100)>
#getMetadata(b)# #b#</br>

<cfset c = int(b)>
#getMetadata(c)# #c#</br>
</cfoutput>

结果输出如下所示。如您所见,它将其从 Double 转换为 BigDecimal 并避免了精度问题。

class coldfusion.runtime.CFDouble 69.35
class java.math.BigDecimal 6935.00
class java.lang.Long 6935

您可以查看结果 here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。