SQL Round转换为float

时间:2017-09-14 08:05:25

标签: sql sql-server casting rounding

我在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的投射舍入到之前浮动,我得到相同的值。这是一个错误吗?

3 个答案:

答案 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)中,由于舍入浮动,我在某些情况下得到的差别很小。