3

这里的很多答案都说使用

SELECT @value - FLOOR(@value)

获取数字的小数部分。有关示例,请参见此处此处

当我这样做时,我得到了我认为奇怪的行为。

DECLARE @test DECIMAL(38, 8)
SET @test = 123.05468800

SELECT @test - FLOOR(@test)

Result: 0

我可以

SELECT 123.05468800 - FLOOR(123.05468800)

Result: 0.05468800

我可以更改@testto的类型FLOAT并且它可以工作。也按预期FLOOR(@test)返回。123

我想这与小数类型的精度有关,但我能找到的关于该主题的唯一 MSDN 页面非常稀疏。

发生什么了?为什么我没有得到小数部分.05468800?我应该做什么或用什么来得到这个?

4

1 回答 1

4
DECLARE @test DECIMAL(38, 8), @test2 DECIMAL(28, 8)
SET @test = 123.05468800
SET @test2 = 123.05468800

SELECT 
    @test as test, 
    FLOOR(@test) AS floortest, 
    @test-FLOOR(@test) AS broken, 
    @test - CAST(FLOOR(@test) AS DECIMAL(38, 8)) AS fixed
INTO gbntest;

SELECT 
    @test2 as test, 
    FLOOR(@test2) AS floortest, 
    @test-FLOOR(@test2) AS working
INTO gbntest2;

SELECT 
    123.05468800 as test,
    FLOOR(123.05468800) as floortest,
    123.05468800 - FLOOR(123.05468800) as working
INTO gbntest3;

SELECT * FROM INFORMATION_SCHEMA.COLUMNS C WHERE C.TABLE_NAME LIKE 'gbntest%';
DROP TABLE gbntest;
DROP TABLE gbntest2;
DROP TABLE gbntest3;

注意 gbntest 的中间 2 是decimal (38,0)

但是,使用常量或decimal (28,8)它可以工作。(29,8)也是如此(30,8)

但后来和(31,8)你一起(38,7)回来。

MSDN “精度、比例和长度”描述了原因

                precision                                 scale
 ...
 e1 - e2        max(s1, s2) + max(p1-s1, p2-s2) + 1       max(s1, s2)

对于 (31,8),您的精度为 (40, 8)

max(8,0) + max(31-8, 31-0) + 1 -> 8 + 31 + 1 -> 40
max(8,0) -> 8

(40,8) 调低至(38,6)。所以我在某个地方把我的计算加了:-)但我希望你明白……

于 2012-01-24T19:48:48.453 回答