我在SQL Server 2014中遇到问题:当我将数字舍入到2位小数时,如果我之前转换为浮点数,有时舍入的数字是不同的。 例如,如果我执行:
select round(cast(3.945 as float),2)
select round(3.945,2)
我有:
3.94
3.950
但如果我执行:
select round(cast(3.935 as float),2)
select round(3.935,2)
我有:
3.94
3.940
似乎不正确,将3.935和3.945的投射舍入到之前浮动,我得到相同的值。这是一个错误吗?
答案 0 :(得分:2)
这里的问题是float是二进制浮点类型,其中表示是值的近似值。浮点数不会无损地转换为基数10或从基数10转换,因为没有10的幂也是2的幂。所以当转换它时,它会以一种舍入错误的方式完成,该错误在舍入之前推送值阈值。
奇怪的是我无法在PostgreSQL上重现相同的行为,我不完全确定原因(可能是在PostgreSQL上,round取一个数值,这会强制转换回来)。
切勿使用需要绝对精度的浮子。这不仅发生在数据库中,也发生在几乎所有编程语言中。
答案 1 :(得分:0)
正如@ChrisTravers在his answer中所说,对浮点数进行四舍五入的问题是你没有得到精确算术。也就是说,这解释了为什么round(3.945,2)
向3.95
向下舍入,而round(3.945E0,2)
有效地向下舍入为3.94
。
如果您想知道为什么在某些情况下您会看到超过2个小数位,那是因为您正在处理的类型。即3.94
是浮点数,因此不具有指定的小数位数;而3.950
是围绕decimal(4,3)
的结果;即使我们舍入到小数点后2位也不会影响类型的精确度(即它仍然decimal(4,3)
;不会转换为decimal(4,2)
或{{1 }})。
如果此舍入的目的是出于显示目的,您最好使用decimal(3,2)
功能。即。
str
select str(3.945,4,2) --decimal
在上面,4是字符串的长度(即包括小数点作为字符),2是要显示的小数位数。
注意:在这种情况下,您将数据类型转换为select str(3.945E0,4,2) --float
。
以下代码可让您查看执行操作后获得的类型:
varchar(4)
答案 2 :(得分:0)
谢谢!我只是问这个,因为我在SQL中有一个表,其中的数据是使用一个函数来计算的,该函数使用此转换来浮动。我想从相同的原始数据重新创建相同的表,但是在另一个程序(Nav)中,由于舍入浮动,我在某些情况下得到的差别很小。