3

我计算总和并将它们放入我使用 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给与我的值如此接近的值,以至于小数点后至少第二个数字被正确舍入?

4

1 回答 1

4

简短的回答:

使用 double 类型而不是 float 类型,即javacast("double", value)

更长的答案:

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

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

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

double:双精度数据类型是双精度 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 显示值。

于 2017-04-10T15:35:03.103 回答