关于用len()函数统计float类型函数的长度问题

manucjj 2012-09-28 02:50:45
测试代码如下:
declare @a int
declare @b int
declare @c int
declare @d float
set @b=CONVERT(int,15*RAND()+2)
set @c=0
set @a=CONVERT(int,2*RAND())
set @d=convert(float,@a)/10
while @c<@b
begin
set @d=(@d+convert(float,@a))/10
select @a,@b,@d
select LEN(@d)
set @a=CONVERT(int,2*RAND())
set @c=@c+1
end
select @a,@b,@d
select LEN(@d)

运行结果如下:
(无列名) (无列名) (无列名) (无列名)
0 8 0 1
(无列名) (无列名) (无列名) (无列名)
1 8 0.1 3
(无列名) (无列名) (无列名) (无列名)
0 8 0.01 4
(无列名) (无列名) (无列名) (无列名)
0 8 0.001 5
(无列名) (无列名) (无列名) (无列名)
1 8 0.1001 6
(无列名) (无列名) (无列名) (无列名)
0 8 0.01001 7
(无列名) (无列名) (无列名) (无列名)
1 8 0.101001 8
(无列名) (无列名) (无列名) (无列名)
1 8 0.1101001 6

(无列名) (无列名) (无列名) (无列名)
1 8 0.1101001 6

看上面的结果,为什么会出现@d的小数位数增加,但是len(@d)的长度反而减少的情况呢?加粗和红字的部分,有无人能解释一下?
...全文
496 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
ggewt2td 2012-10-01
  • 打赏
  • 举报
回复
float这类近似值的类型,尽量少用,
如果一定要用,一定要知道它是近似值,并非真实值。
ggewt2td 2012-10-01
  • 打赏
  • 举报
回复
超过7位有效位,会自动四舍五入的。


declare @a float
set @a = 0.1101004
select @a,len(@a),ltrim(@a),ltrim(cast(@a as decimal(20,10)))

set @a = 0.1101005
select @a,len(@a),ltrim(@a),ltrim(cast(@a as decimal(20,10)))
ggewt2td 2012-10-01
  • 打赏
  • 举报
回复
declare @a float
set @a = 0.1101001
select @a,len(@a),ltrim(@a),ltrim(cast(@a as decimal(20,10)))

float有效位数很小,只有7位,

而你红色的那行,已经超过7位了,

所以建议你用decimal, decimal有效位数很长,而且是真实值。

至于你说decimal后面补0的情况,你格式化一下数字就行了,有很多格式话字符的方法。

不能因为显示的原因,而让计算不正确。

编程的一条铁的规定,就是先要保证数据正确,然后才去考虑其它问题。

而你为了贪图那点显示格式,而让数据计算不正确。

只要是计算,都采用decimal来计算。

除非是天文数字 。
manucjj 2012-09-29
  • 打赏
  • 举报
回复
但是decimal对于小数位数不确定的数据要统计其长度这个不太可取啊!decimal会对小数位数不足的部分自动补0,得出的结果就不是我想要的结果了。
ggewt2td 2012-09-29
  • 打赏
  • 举报
回复
你不要用 float,用decimal 吧,
看你那么纠结的,

float本来就不定长度的,而且是近似值,
什么叫近似值,你先了解一下浮点数是如何表示的,谷歌一下“IEEE浮点数格式”

decimal是真实值,
manucjj 2012-09-28
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
引用 9 楼 的回复:
SELECT
LEN(@d) ,
LTRIM(@d),
len(LTRIM(@d))
@d会转成字符 再计算长度
水哥不是已经解释了么
[/Quote]
但是问题是就算算上小数点,结果还是和实际位数不符啊!有时结果和实际是一样的,至于什么时候会出现结果和实际位数不一致的情况,也没有能够给个确切的解释
DBA_磊仔 2012-09-28
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
SELECT
LEN(@d) ,
LTRIM(@d),
len(LTRIM(@d))
@d会转成字符 再计算长度
[/Quote]水哥不是已经解释了么
manucjj 2012-09-28
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
最好使用DATALENGTH()函数来获取长度。
[/Quote]
用DATALENGTH()函数获取float类型函数的长度不管实际的数有多少位,长度都会显示是8,所以这个不可取啊!

话说,怎么就没人能够解释到这么灵异的现象呢?
水族杰纶 2012-09-28
  • 打赏
  • 举报
回复
SELECT
LEN(@d) ,
LTRIM(@d),
len(LTRIM(@d))
@d会转成字符 再计算长度
zhengnan2012 2012-09-28
  • 打赏
  • 举报
回复

LEN ( string_expression )
这个要用string类型的。
ttpsan550 2012-09-28
  • 打赏
  • 举报
回复
问题有深度!!!
gogodiy 2012-09-28
  • 打赏
  • 举报
回复
最好使用DATALENGTH()函数来获取长度。
manucjj 2012-09-28
  • 打赏
  • 举报
回复
但是为什么float函数会这样?
manucjj 2012-09-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
select @a,@b,@d,cast(@d as varchar)

select LEN(@d)



Len转长度时,会先将 @d 转成字符串再取长度的,所以你要看它转成字符串时是什么,

它转的时候,会舍掉尾数,对于 float的处理,是很怪异的,因为 float属于近似值,

可以使用 decimal,因为decimal是真实值
[/Quote]
我去试试。
manucjj 2012-09-28
  • 打赏
  • 举报
回复
但是select LEN(@d)返回的却是6,有时会这样,但是有时又不会,有无高手能够解释一下为什么会出现这种现象啊?

ggewt2td 2012-09-28
  • 打赏
  • 举报
回复
select @a,@b,@d,cast(@d as varchar)

select LEN(@d)



Len转长度时,会先将 @d 转成字符串再取长度的,所以你要看它转成字符串时是什么,

它转的时候,会舍掉尾数,对于 float的处理,是很怪异的,因为 float属于近似值,

可以使用 decimal,因为decimal是真实值
jinjazz 2012-09-28
  • 打赏
  • 举报
回复
select LEN(0.1101001)

返回的是9

22,295

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧