11

我需要在 SQL Server 中将浮点数转换为十进制(28,10)。我的问题是,由于浮点数的性质以及转换的完成方式,简单地转换浮点数可能会使我的用户认为它是错误的数字。

例如:

Float:               280712929.22 
Cast as Decimal:     280712929.2200000300
What I think I want: 280712929.2200000000

我对 float 的工作方式有所了解(它是一种近似的数据类型等),但诚然不足以理解为什么它会在末尾添加 300。它只是作为转换的副作用的垃圾,还是以某种方式更准确地表示浮点实际存储的内容?对我来说,它看起来像是凭空而来的精确度。

最终,我需要它是准确的,但也要看起来“正确”。我想我需要得到那个底部数字,因为看起来我刚刚添加了尾随零。这可能吗?这是一个好主意还是坏主意,为什么?欢迎提出其他建议。

其他一些例子:

Float:           364322379.5731
Cast as Decimal: 364322379.5730999700
What I want:     364322379.5731000000

Float:           10482308902
Cast as Decimal: 10482308901.9999640000
What I want:     10482308902.0000000000

旁注:我将这些值放入的新数据库表可由我的用户读取。他们现在实际上只需要两位小数,但将来可能会改变,所以我们决定使用 Decimal(28,10)。长期目标是将我获取数据的浮点列也转换为十进制。

编辑:有时我的浮点数比我需要的多,例如:-0.628475064730907。在这种情况下,转换为 -0.6284750647 就可以了。我基本上需要我的结果在浮点数的末尾添加零,直到我有 10 个小数位。

4

3 回答 3

9

您需要进行一次四舍五入,一次添加小数位(当然,还有其他方法,使用STRROUND):

DECLARE @c TABLE(x FLOAT);

INSERT @c SELECT 280712929.22;
INSERT @c SELECT 364322379.5731;
INSERT @c SELECT 10482308902;

SELECT x, 
    d = CONVERT(DECIMAL(28,10), x), 
    rd = CONVERT(DECIMAL(28,10), CONVERT(DECIMAL(28,4), x))
FROM @c;

结果:

x               d                       rd
--------------  ----------------------  ----------------------
280712929.22    280712929.2200000300    280712929.2200000000
364322379.5731  364322379.5730999700    364322379.5731000000
10482308902     10482308902.0000000000  10482308902.0000000000

如果您希望它准确且看起来正确,请停止使用FLOAT,这是一种近似数据类型,并且对于大多数没有严格数学背景的人来说是违反逻辑的。使用DECIMAL比您需要的更大的比例,并将其格式化为您现在需要的小数位数(在您的查询中,或创建一个视图,或创建一个计算列)。如果您存储的信息比现在需要的多,您以后总是可以公开更多信息。您还可以选择不让用户直接访问您的表。

于 2012-06-20T12:17:11.970 回答
3

我不确定这是否属于 necroposting,但我最近遇到了类似的问题,所以我想我可能会发布。

这可能像罪一样丑陋,但似乎有效(根据上面亚伦的回应修改)。

DECLARE @myTable TABLE(x FLOAT);

INSERT INTO @myTable VALUES
   (280712929.22),
   (364322379.5731),
   (10482308902),   
   (-0.628475064730907);

SELECT x, 
       d = CONVERT(DECIMAL(28,10), x),                 
       NewDec = CONVERT(DECIMAL(28,10),           
                        CONVERT(DECIMAL(16,15), 
                                LEFT(CONVERT(VARCHAR(50), x, 2),17)) 
                        * POWER(CONVERT(DECIMAL(38,19),10),  
                                RIGHT(CONVERT(varchar(50), x,2),4)))                       
FROM @myTable; 

结果:

x                   d                       NewDec
------------------  ----------------------  ----------------------
280712929.22        280712929.2200000300    280712929.2200000000
364322379.5731      364322379.5731000300    364322379.5731000000
10482308902         10482308902.0000000000  10482308902.0000000000
-0.628475064730907  -0.6284750647           -0.6284750647
于 2015-08-25T05:36:17.133 回答
1

当我需要将大数据表从浮点数转换为十进制数(28,15)时,我遇到了这个问题。正如@Dan 答案的评论中所指定的,他的答案对于某些值没有按预期工作。

这是我用来进行更新的最终版本

DECLARE @myTable TABLE(x FLOAT);

INSERT INTO @myTable VALUES
(280712929.22),
(364322379.5731),
(10482308902),   
(-0.628475064730907),   
(-0.62847506473090752665448522),
(8.828),
(8.9),
(8.999),
(8),
(9),
(0.000222060864421707),
(5.43472210425371E-323),
(1.73328282953587E+81);

SELECT x, 
   d = CONVERT(DECIMAL(28,15), ROUND( CONVERT(DECIMAL(28,15),           
                CONVERT(DECIMAL(16,15), 
                        LEFT(CONVERT(VARCHAR(50), x, 2),17)) 
                * POWER(CONVERT(DECIMAL(38,19),10),  
                         CASE   
  WHEN RIGHT(CONVERT(varchar(50), x,2),4) > 12 THEN 12
  ELSE RIGHT(CONVERT(varchar(50), x,2),4)
  END)), 14 )),

 SimpleVarchar = TRY_CONVERT(VARCHAR(50), x),
 AnsiVarchar = TRY_CONVERT(VARCHAR(50), x, 2)
 FROM @myTable; 

因为我在小数点 14 上四舍五入,所以我失去了一小部分精度。但在我的情况下这是可以接受的。

于 2018-08-28T13:48:19.950 回答