JavaCast慷慨地浮动



我计算总和并将其放入我在 Coldfusion 中使用 POI 库生成的 Excel 工作表中。由于 Java 库需要类型化的变量,我总是称之为setCellValue( JavaCast( "float", myVar ) )。我被.03意识到了一个舍入错误。比通常知道的铸造后漂浮的差异要大得多。

<cfset s = 601761.66>
<cfoutput>
#s#<br>
#JavaCast( "float", s )#<br>
#LSNumberFormat( JavaCast( "float", s ), ".0000000" )#<br><br>
</cfoutput>
  • 第一行打印601761.66
  • 第二轮601761.7
  • 然而,第三个打印:601761,6875000等于601761,69并且比我输入的值大.03

我知道,LSNumberFormat返回一个字符串。我叫它只是为了比较。POI似乎存储浮点值,Excel最终像LSNumberFormat一样显示该值。

如何将一个值传递给setCellValue,该值与我的值非常接近,以至于至少十进制后的第二个数字被正确舍入?

简短回答:

使用双精度类型而不是浮点型,即javacast("double", value)

更长的答案:

Cell.setCellValue() 方法实际上需要 Double 类型(不是 Float)。Double 也是 CF 用于大多数数值运算和函数的。将 Float 传递到这些方法中时,它会隐式转换为 Double。该转换(间接)导致意外结果。

原因是浮点型和双精度型都是近似类型。但是,Double 具有更高的精度:

float

float数据类型是单精度32位IEEE 754浮点数。

双精度:双精度数据类型是双精度64位IEEE 754浮点数。

所以正如这个线程指出的(强调我的):

这并不是说你实际上获得了额外的精度 - 而是 浮点数没有准确代表您的目标数字 原来。双精度准确表示原始浮点数; toString 显示已经存在的"额外"数据。 ...[当转换为双精度时,它]将具有完全相同的值,但是当您将其转换为字符串时,它将"相信"它精确到更高的精度,因此不会尽早四舍五入,并且您将看到已经存在的"额外数字",但对您隐藏

这就是为什么"601761.66">

和"601761.6875"在转换为浮点数时似乎四舍五入为"601761.7",但在转换为双精度时显示预期。

<cfscript>
value1 = "601761.66";
value2 = "601761.6875";
WriteOutput("<br>[Float] "& value1 &" = "& javacast("float", value1));
WriteOutput("<br>[Float] "& value2 &" = "& javacast("float", value2));
WriteOutput("<br>[Float=>Double] "& value1 &" = "& javacast("double", javacast("float", value1)));
WriteOutput("<br>[Double] "& value1 &" = "& javacast("double", value1));
WriteOutput("<br>[Double] "& value2 &" = "& javacast("double", value2));
</cfscript>

输出:

[Float] 601761.66 = 601761.7
[Float] 601761.6875 = 601761.7
[Float=>Double] 601761.66 = 601761.6875
[Double] 601761.66 = 601761.66
[Double] 601761.6875 = 601761.6875

注意:CF 使用 Float.toString() 和 Double.ToString() 通过 cfoutput/writeOutput/cfdump 显示值。

最新更新