SQL四舍五入并非总是向上取整

4
我是一名有用的助手,可以为您翻译文本。
我正在尝试在SQL中进行四舍五入,但结果非常奇怪;以下是我的操作:
我正在使用Mssql。
我有一个选择语句:
Select num1, num2, num1 * num2, round(num1 * num2, 2)
from myTable

数据类型:

num1 是浮点数

num2 是货币类型

如果 num1 的值为 15,num2 的值为 0.033,则结果如下:

15,0.033,0.495,0.5

问题在于当 num1 的值为 5,num2 的值为 0.045 时,结果如下:

5,0.045,0.225,0.22

有人有想法吗?


1
你确定应该使用MONEY数据类型吗?这里有一篇非常有说服力的文章,说明为什么应该尽可能避免使用它,而改用decimal:http://sqlserverpedia.com/blog/sql-server-bloggers/throw-your-money-away/ - David
我在我的sqlect中尝试了这个:round(convert(decimal(10, 3), num2) * num1, 2),但它不起作用 :( - GregM
有趣...这对我有效...试试这个:选择 round(CONVERT(decimal(10,3), 0.045) * 5, 2)。只是执行:"select round(5 * 0.045, 2)",也能给我正确的结果。 - David
是的,这对我也起作用,但当我转换我的货币值时它不起作用。所以问题确实出在我的货币列上,但为什么呢! :) - GregM
4个回答

5
如果您在网格视图模式下查看此可运行示例(请注意,文本模式不同),您应该会看到问题:
DECLARE @tbl AS TABLE (num1 float, num2 money);
INSERT INTO @tbl VALUES (15, 0.033), (5, 0.045);

Select num1, num2, num1 * num2, round(num1 * num2, 2)
from @tbl;

请注意,该数字实际上是0.224999999,四舍五入为0.22 - 当查看SQL Server的非二进制输出时需要小心 - 它有时会以您意想不到的方式将数字转换为文本。
这来自于浮点数 * 货币操作,导致浮点数受到二进制表示问题的影响。
您应该考虑您的浮点值意味着什么,并考虑改用十进制,以及查看十进制运算的精度和比例规则。请注意,货币只与decimal(19,4)略有相似之处。

1
你可以尝试使用 long 类型而不是 float。我认为这是与浮点数精度有关的问题。

抱歉,我正在使用 MSSQL 数据库,已经编辑了我的问题。我认为 MSSQL 中不存在 long 类型。 - GregM
1
如果你想要精确的数学计算,永远不要使用浮点数。请使用十进制类型。 - HLGEM

0
你使用的是哪个版本的SQL?
在查询分析器中尝试这段代码。

DECLARE @num1 float
DECLARE @num2 money

SET @num1 = 15
SET @num2 = 0.033

SELECT
@Num1,
@Num2,
@Num1 * @Num2,
ROUND(@Num1 * @Num2,0),
ROUND(@Num1 * @Num2,1),
ROUND(@Num1 * @Num2,2),
ROUND(@Num1 * @Num2,3)

浮点数是一种近似值而不是真实数字。请使用十进制数。


DECLARE @num1 decimal
DECLARE @num2 money

SET @num1 = 5
SET @num2 = 0.045

SELECT
@Num1,
@Num2,
@Num1 * @Num2,
ROUND(@Num1 * @Num2,2),
ROUND(CAST(@Num1 as money) * @Num2,2)

抱歉,我在round函数中忘记了",2",但这个是正确的。这是结果:15 0.033 0.495 0 0.5 0.5 0.495;这是我的另一组数据,其中的5和0.045让我有些困扰。 - GregM

0

我已经将我的浮点列转换为货币,现在似乎可以正常工作了。

谢谢大家!


你应该避免使用货币数据类型。我强烈建议您考虑两个值的范围,并使用适当的十进制,了解小数位数和精度的规则,并根据分数便士做出适当的决策。另外,据我所知,将两个货币类型相乘从来就没有意义-您永远不会有$x$和$y$的$ $ $,只有通过除法获得标量。否则,您将得到$x*y$ $^2$ 个美元-像平方英尺、立方米或其他任何东西一样,美元没有平方。 - Cade Roux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接