带truncate的SQL ROUND()函数接受119.1并返回119.09
我有英镑和便士的数据存储在串联字符串中(不幸的是,没有办法解决这个问题),但不能保证小数点后2位 例如,我可能会得到一个值带truncate的SQL ROUND()函数接受119.1并返回119.09,sql,sql-server,casting,rounding,truncate,Sql,Sql Server,Casting,Rounding,Truncate,我有英镑和便士的数据存储在串联字符串中(不幸的是,没有办法解决这个问题),但不能保证小数点后2位 例如,我可能会得到一个值119.109,因此必须将其转换为带截断的两位小数,即119.10,而不是119.11 出于这个原因,我避免使用“CAST as Decimal”,因为我不想四舍五入。相反,我使用ROUND(amount,2,1)强制截断小数点后2位 这在很大程度上起作用,但有时表现出奇怪的行为。例如,119.10输出为119.09。这可以复制为: ROUND(CAST('119.10' A
119.109
,因此必须将其转换为带截断的两位小数,即119.10
,而不是119.11
出于这个原因,我避免使用“CAST as Decimal”,因为我不想四舍五入。相反,我使用ROUND(amount,2,1)
强制截断小数点后2位
这在很大程度上起作用,但有时表现出奇怪的行为。例如,119.10
输出为119.09
。这可以复制为:
ROUND(CAST('119.10' AS varchar),2,1)
我的目标字段是十进制(19,4)(但小数点后第3位和第4位始终为0,这是一个金融系统,所以总是英镑和便士…)
我假设问题与取整一个varchar有关……但我不知道如何解决这个问题,而不必强制转换,从而以这种方式引入取整
这里发生了什么
非常感谢您的任何想法。这是由于浮点数的工作方式,以及您的字符串在四舍五入之前被隐式转换为浮点数的事实。在您的测试用例中:
ROUND(CAST('119.10' AS varchar),2,1)
您正在将119.10
隐式转换为float,以便可以将其传递给ROUND
函数,119.10不能存储为float,运行以下操作即可证明:
SELECT CAST(CONVERT(FLOAT, '119.10') AS DECIMAL(30, 20))
返回:
119.09999999999999000000
因此,当你用truncate四舍五入时,得到119.09
不管它值多少钱,您都应该使用哪种dbms?不同的产品可能会有不同的表现…感谢您的关注。我使用的是MS SQL Server 2008我想到的第一件事:trunc(x*100)/100谢谢,这很有意义。然而,如果我显式地转换为十进制,那么这不会引入我想要避免的舍入吗?很好的一点,你就不能从便士字符串中取前两位吗?e、 g.磅+”.+左(便士,2)
那就行了!检查了我得到的数据…不幸的是,虽然有时我可能会得到一个“119”的值…因此必须假设为0便士…所以可能必须先检查一个“.”。乘以100,将结果加上底数,然后除以100会有什么好处?或者仍然存在固有的强制转换舍入如果pence是它自己的varchar字段,您可以使用磅+'.+右('00'+左(pence,2))
,这将确保pence中始终至少有2位数字。