SQL 带截断的 ROUND() 函数需要 119.1 和 returns 119.09
SQL ROUND() function with truncate takes 119.1 and returns 119.09
我将英镑和便士的数据存储在连接的字符串中(不幸的是,没有办法解决这个问题)但不能保证小数点后两位。
例如我可能会得到 119.109
的值,因此必须截断后将其转换为小数点后 2 位,即 119.10
,而不是 119.11
.
出于这个原因,我避免 "CAST as Decimal" 因为我不想四舍五入。相反,我使用 ROUND(amount, 2, 1)
强制截断小数点后 2 位。
这在大多数情况下都有效,但有时会表现出奇怪的行为。例如,119.10
输出为 119.09
。这可以复制为:
ROUND(CAST('119.10' AS varchar),2,1)
我的目标字段是 Decimal(19,4)(但是第三和第四位小数总是 0,这是一个金融系统所以总是英镑和便士...)。
我认为问题与对 varchar 进行舍入有关....但我不知道如何解决这个问题而不必 CAST
因此以这种方式引入舍入?
这里发生了什么?
非常感谢任何想法。
这是由于浮点数的工作方式,以及您的字符串数字在四舍五入之前被隐式转换为浮点数这一事实。在您的测试用例中:
ROUND(CAST('119.10' AS varchar),2,1)
您正在隐式地将 119.10
转换为浮点数,以便它可以传递给 ROUND
函数,119.10 完全不能存储为浮点数,运行 证明如下:
SELECT CAST(CONVERT(FLOAT, '119.10') AS DECIMAL(30, 20))
哪个returns:
119.09999999999999000000
因此,当您使用 truncate 对其进行舍入时,您将得到 119.09。
物有所值,你应该always specify a length when converting to, or declaring a varchar
我将英镑和便士的数据存储在连接的字符串中(不幸的是,没有办法解决这个问题)但不能保证小数点后两位。
例如我可能会得到 119.109
的值,因此必须截断后将其转换为小数点后 2 位,即 119.10
,而不是 119.11
.
出于这个原因,我避免 "CAST as Decimal" 因为我不想四舍五入。相反,我使用 ROUND(amount, 2, 1)
强制截断小数点后 2 位。
这在大多数情况下都有效,但有时会表现出奇怪的行为。例如,119.10
输出为 119.09
。这可以复制为:
ROUND(CAST('119.10' AS varchar),2,1)
我的目标字段是 Decimal(19,4)(但是第三和第四位小数总是 0,这是一个金融系统所以总是英镑和便士...)。
我认为问题与对 varchar 进行舍入有关....但我不知道如何解决这个问题而不必 CAST
因此以这种方式引入舍入?
这里发生了什么?
非常感谢任何想法。
这是由于浮点数的工作方式,以及您的字符串数字在四舍五入之前被隐式转换为浮点数这一事实。在您的测试用例中:
ROUND(CAST('119.10' AS varchar),2,1)
您正在隐式地将 119.10
转换为浮点数,以便它可以传递给 ROUND
函数,119.10 完全不能存储为浮点数,运行 证明如下:
SELECT CAST(CONVERT(FLOAT, '119.10') AS DECIMAL(30, 20))
哪个returns:
119.09999999999999000000
因此,当您使用 truncate 对其进行舍入时,您将得到 119.09。
物有所值,你应该always specify a length when converting to, or declaring a varchar