1

将双精度值插入具有小数精度的数据库表时遇到问题。我正在使用 MS SQL Server 版本 10.0.4000 下面是一个小数列有 4 个小数位的示例表。

create table test (
test decimal (18,4))

当我通过 MSSQL 控制台插入值“36.78675”时,它会被四舍五入,36.7868因为该字段只有 4 位小数。这可以。

DECLARE @T DECIMAL(18, 5)

SET @T = 36.78675

insert into test values(@T)

select * from test

但是当我通过我的 java 代码(MS SQL JDBC 驱动程序)执行等效插入(使用准备好的语句)时,数据存储在表中是36.7867. 如果我有一个类似的值36.786750001,控制台和 JDBC 都会舍入到36.7868. 我使用的 java 对象是 double 的。我用双值调用 setDouble() 。在这里它会自动选择数据类型。但是还有另一种 JDBC 方法,它采用对象和数据类型。使用它,我用 DECIMAL 和 FLOAT 类型进行了测试。所有人都给出了相同的结果。我什至将 jdbc 驱动程序更改为 I-net。也有同样的结果。

有人知道为什么通过驱动程序进行舍入的工作方式不同吗?是否有任何设置使其表现得像控制台?

4

1 回答 1

4

这是因为二进制浮点的性质,这是您使用的double(在 Java 中)。

最接近 36.7875的确切值是double

36.7867499999999978399500832892954349517822265625

这将四舍五入为 36.7867。而最接近 36.78750001的确切值是double

36.786750000099999624580959789454936981201171875

这将四舍五入为 36.7878。这就是你得到这种行为的原因。控制台可能将输入视为十进制数,而不是转换为二进制浮点数。

如果精确的十进制数字对您很重要,您可能不应该使用二进制浮点类型 -BigDecimal而是使用。

您应该真正考虑一下您的价值代表什么。如果它是一个物理连续值,例如身高、长度或重量,那么使用double可能毕竟是合适的——但你不应该对这样的情况感到困惑。如果它是具有离散(基于十进制)值的人工构造,例如货币值,那么您绝对应该使用BigDecimal,或者简单地缩放一个整数。

于 2013-02-20T07:13:09.777 回答