隐式转换和舍入

发布于 2024-10-07 13:16:05 字数 684 浏览 0 评论 0原文

刚刚遇到一个有趣的:

declare @test as int
set @test = 47

select @test * 4.333

returns 203.651

declare @test as int
set @test = 47

declare @out as int
set @out = (select @test * 4.333)

select @out

returns 203

declare @test as int
set @test = 47

declare @out as int
set @out = round((select @test * 4.333),0)

select @out

returns 204

现在我知道为什么它会这样做。这是因为存在从小数到整数的隐式转换,因此需要截掉小数位(因此为 203),而如果我在隐式转换之前四舍五入,则会得到 204。

我的问题是为什么当 SQL Server 执行隐式转换时转换不是也四舍五入吗? 我知道如果我有一个很大的数字,并且需要将其存储在一个小地方,我要做的第一件事就是对其进行四舍五入,以便尽可能接近原始值数量尽可能。

对我来说这似乎并不直观。

Just come across an interesting one:

declare @test as int
set @test = 47

select @test * 4.333

returns 203.651

declare @test as int
set @test = 47

declare @out as int
set @out = (select @test * 4.333)

select @out

returns 203

declare @test as int
set @test = 47

declare @out as int
set @out = round((select @test * 4.333),0)

select @out

returns 204

Now I know why it does this. Its because there is an implicit conversion from decimal to int, therefore the decimal places need chopped off (hence 203), whereas if I round prior to the implicit conversion I get 204.

My question is why when SQL Server does an implicit conversion is it not also rounding? I know if I had a big number, and it needed stored in a small place, the first thing I'd do would be to round it so as to be as close to the original number as possible.

It just doesn't seem intuitive to me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

流星番茄 2024-10-14 13:16:05

这让我开始阅读,答案似乎显然不能令人满意,我能找到的最早的 SQL 参考(ANSI 92 可用 此处)在 4.4.1 数字特征 节中指出

每当将精确或近似数值分配给
代表精确数值的数据项或参数,
其值的近似值,保留领先的显着性
数据中表示四舍五入或截断后的数字
目标的类型。该值被转换为具有精度和
目标的规模。选择是否截断或舍入
是实现定义的。

这让 Microsoft 选择为 T-SQL 实现两者中的哪一个,我假设为了简单起见,他们选择了截断。从 关于舍入的维基百科文章来看,这似乎并不是一个不常见的决定那天。

有趣的是,根据我发现的文档,只有转换为整数才会导致截断,其他转换会导致四舍五入。尽管出于某种奇怪的原因,从货币到整数的转换似乎与趋势相反,因为它允许四舍五入。

From     To       Behaviour

numeric  numeric  Round

numeric  int      Truncate

numeric  money    Round

money    int      Round

money    numeric  Round

float    int      Truncate

float    numeric  Round

float    datetime Round

datetime int      Round

表来自 此处

This got me reading and the answer seems to be distinctly unsatisfying, The earliest SQL reference I've been able to find (ANSI 92 available here) in section 4.4.1 Characteristics of numbers states that

Whenever an exact or approximate numeric value is assigned to a
data item or parameter representing an exact numeric value,
an approximation of its value that preserves leading significant
digits after rounding or truncating is represented in the data
type of the target. The value is converted to have the precision and
scale of the target. The choice of whether to truncate or round
is implementation-defined.

Which leaves it up to Microsoft which of the two they chose to implement for T-SQL and I assume for the sake of simplicity they chose truncation. From the wikipedia article on rounding it seems that this wasn't an uncommon decision back in the day.

It's interesting to note that, according to the documentation I found, only conversions to integers cause truncation, the others cause rounding. Although for some bizarre reason the conversion from money to integer appears to buck the trend as it's allowed to round.

From     To       Behaviour

numeric  numeric  Round

numeric  int      Truncate

numeric  money    Round

money    int      Round

money    numeric  Round

float    int      Truncate

float    numeric  Round

float    datetime Round

datetime int      Round

Table from here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文