再次请教(16进制转换为10进制)搞定结贴

taoxianxue 2006-04-27 10:30:15

CREATE FUNCTION dbo.Hex2Dec (@vNCarryValue varchar(100))
RETURNS dec
AS
BEGIN
declare @iValue dec(12,2)
,@iCount int
,@iLen int
,@iPos int
select @iValue=0.00,@iCount=len(replace(@vNCarryValue,'0',''))
while(@iCount>=1)
begin
select @vNCarryValue=right(@vNCarryValue,len(@vNCarryValue)-
charindex('1',@vNCarryValue)+1)
,@iLen=len(@vNCarryValue)
,@iPos=@iLen-charindex('1',@vNCarryValue,0)
,@vNCarryValue=right(@vNCarryValue,len(@vNCarryValue)-
charindex('1',@vNCarryValue))
,@iValue=@iValue+power(16,@iPos)
,@iCount = @iCount-1
end
return @iValue
END


不过我使用的时候好像取得数据不对
如select dbo.Hex2Dec ('468DB371') ; 结果为8
...全文
1220 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
liusujian02 2006-04-28
  • 打赏
  • 举报
回复
如果你要是考虑小数的问题,也不难啊
只是觉得你的16进制怎么和预期的不一样呢?
liusujian02 2006-04-28
  • 打赏
  • 举报
回复
回答你的问题之前,先讲两个问题:
1、请问select len('12340sdf'):你觉得这个结果是4还是8
我测试过:结果是8,说明0的问题这里不用考虑
2、我认为无论用T-SQL语言写,还是用C写,解决问题的思路一定是清楚的
并且是合理的
3、我并没有模仿楼上所写,是本人自己写的
以下是我的解决方案:
也许不是最好的,但是至少是正确的,同时也希望各位高手提出更好的
的解决方案,大家共同学习,我认为T-SQL语言是非常强大的,应该认真学习
CREATE FUNCTION dbo.Hex2Dec(@vNCarryValue varchar(100))
RETURNS dec
AS
BEGIN
declare @iValue dec(12,2),
@iCount int,
@iLen int,
@iPos int,
@CurrentLen int
--定义局部变量
select @iValue=0.00,@iCount=len(@vNCarryValue)
set @CurrentLen = @iCount
--ivalue是用来存储最终结果
--@iCount是用来存储有多少个16进制字符,以决定他的最高幂次(@iCount-1)
declare @temp int
while(@CurrentLen>=1)
begin
--程序做的第一件事情:取最左边或最右边的一个字符,
--这里按照作者意思,取最右边的一个字符,取出它的ASCII值
set @temp = ASCII(right(@vNCarryValue,1))
if(@temp>=65 and @temp <=70)
set @temp = @temp-55
if(@temp>=97 and @temp <=102)
set @temp = @temp-87
if(@temp>=48 and @temp <=57)
set @temp = @temp-48
--这里最好加一些判断(省略)
--程序做的第二件事情:累加操作
set @iValue =@iValue+@temp*power(16,@iCount - @CurrentLen)
--程序做的第三件事情:截取字符串
set @CurrentLen = @CurrentLen - 1
set @vNCarryValue = substring(@vNCarryValue,1,@CurrentLen)
end

return @iValue
END

测试程序:
select dbo.Hex2Dec('ab')

说明:其实程序需要作出很多判断会不会益出现象,呵呵
有什么问题liusujian-duck@163.com 联系吧

桂林电子科技大学计算机系
信息管理与信息系统
2006.4.27
xeqtr1982 2006-04-28
  • 打赏
  • 举报
回复
收藏!学习
Yang_ 2006-04-28
  • 打赏
  • 举报
回复
格式变得如此奇怪
Yang_ 2006-04-28
  • 打赏
  • 举报
回复
呵呵,需要学习浮点数的16进制表示法,算补课吧

叫作业了,代码显得很笨拙,不管了

--16转2函数
CREATE function Hex2Bin(
@h varchar(50)
)
returns varchar(100)
as
begin
declare @r varchar(100)
set @r=''
declare @i int
set @i=1
declare @t varchar(2)
while @i<=len(@h)
begin
set @t=substring(@h,@i,1)
select @r=@r+case @t
when '0' then '0000'
when '1' then '0001'
when '2' then '0010'
when '3' then '0011'
when '4' then '0100'
when '5' then '0101'
when '6' then '0110'
when '7' then '0111'
when '8' then '1000'
when '9' then '1001'
when 'A' then '1010'
when 'B' then '1011'
when 'C' then '1100'
when 'D' then '1101'
when 'E' then '1110'
when 'F' then '1111'
end
set @i=@i+1
end
return @r
end
go


--2进制转整数,计算整数部分
create function bin2int(
@b varchar(100)
)
returns int
as
begin
declare @r int
set @r=0
declare @i int
set @i=1
while @i<=len(@b)
begin
set @r=@r*2+substring(@b,@i,1)
set @i=@i+1
end
return @r
end

go

--2进制转小数部分,本来应该是用float的,为防止溢出,私自扩大了
CREATE function bin2rea(
@b varchar(100)
)
returns real
as
begin
declare @r real
declare @x real
set @r=0
declare @i int
set @i=1
set @x=0.5
while @i<=len(@b)
begin
set @r=@r+@x*cast(substring(@b,@i,1) as int)
set @i=@i+1
set @x=@x/2
end
return @r
end

go


--32位16进制浮点数转换成10进制函数
--作者:Yang_
--欢迎转贴
create function Hex2Dec(
@h varchar(50)
)
returns real
as
begin
declare @r real
set @r=0
declare @b varchar(100)
declare @w varchar(100) --尾数
declare @z varchar(100) --指数
declare @f int --符号
declare @zs real
declare @xs real

set @b=dbo.Hex2Bin(@h)
set @w=substring(@b,10,23)
set @z=substring(@b,2,8)
if left(@b,1)='1'
set @f=-1
else
set @f=1
declare @zws int
set @zws=dbo.bin2int(@z)-127
set @zs=dbo.bin2int('1'+substring(@w,1,@zws))
set @xs=dbo.bin2rea(substring(@w,@zws+1,23-@zws))
set @r=@f*(@zs+@xs)
return @r
end

go

--调用
select dbo.Hex2Dec('468DB371')
itblog 2006-04-28
  • 打赏
  • 举报
回复
:)顶,向各位学习~
Yang_ 2006-04-28
  • 打赏
  • 举报
回复
修正(纯小数问题):

alter function Hex2Dec(
@h varchar(50)
)
returns real
as
begin
--32位16进制浮点数转换成10进制函数
--作者:Yang_
--欢迎转贴
declare @r real
set @r=0
declare @b varchar(100)
declare @w varchar(100) --尾数
declare @z varchar(100) --指数
declare @f int --符号
declare @zs real
declare @xs real

set @b=dbo.Hex2Bin(@h)
set @w=substring(@b,10,23)
set @z=substring(@b,2,8)
if left(@b,1)='1'
set @f=-1
else
set @f=1
declare @zws int
set @zws=dbo.bin2int(@z)-127
if @zws>0
begin
set @zs=dbo.bin2int('1'+substring(@w,1,@zws))
set @xs=dbo.bin2rea(substring(@w,@zws+1,23-@zws))
end
else
begin
set @zs=0
set @xs=dbo.bin2rea(REPLICATE ('0' ,-@zws-1 )+'1'+@w)
end
set @r=@f*(@zs+@xs)
return @r
end


GO

taoxianxue 2006-04-27
  • 打赏
  • 举报
回复
是我弄错了,需要按客户的算法来弄,搞死人了,不过还是非常感谢你
tianhxk 2006-04-27
  • 打赏
  • 举报
回复
睡觉去了!
xeqtr1982 2006-04-27
  • 打赏
  • 举报
回复
468DB371
转成10进制
应该是1183691633
taoxianxue 2006-04-27
  • 打赏
  • 举报
回复
这个是我的16进制
468DB371 468CC133 44DBC8F9 44EB83E4 4217FBEB 41BC98B8 42966B6A

下面是它对应的10进制

468DB371 = 18137.72
468CC133 = 18016.6
44DBC8F9= 1758.28
44EB83E4= 1884.122
4217FBEB= 37.99601
41BC98B8 = 23.57457
42966B6A= 75.20979
tianhxk 2006-04-27
  • 打赏
  • 举报
回复
16进制有小数?
taoxianxue 2006-04-27
  • 打赏
  • 举报
回复
还是不行,我的结果要有小数位,但我试了几个都是转成整数了,结果值很大
tianhxk 2006-04-27
  • 打赏
  • 举报
回复
应该从左往右,非从右往左算
tianhxk 2006-04-27
  • 打赏
  • 举报
回复
其实直接convert为bigint就可以了哦!
tianhxk 2006-04-27
  • 打赏
  • 举报
回复
惭愧!埃啊!晕头了!
这下对了

alter FUNCTION dbo.Hex2Dec (@vNCarryValue varchar(100))
RETURNS dec
AS
BEGIN
declare @iValue numeric(12,2)
,@iCount int
,@iLen int
,@iPos int,
@cChar int
select @iValue=0.00
select @vNCarryValue = ltrim(rtrim(isnull(@vNCarryValue,'')))
while(len(@vNCarryValue)>=1)
begin
set @cChar = ascii(left(@vNCarryValue,1))
if (@cChar >= ascii('0') and @cChar <= ascii('9')) or (@cChar >= ascii('a') and @cChar <= ascii('f')) or (@cChar >= ascii('A') and @cChar <= ascii('F'))
begin
select @iValue = @iValue * 16 + (case when (@cChar >= ascii('0') and @cChar <= ascii('9')) then @cChar - ascii('0')
when (@cChar >= ascii('a') and @cChar <= ascii('f')) then @cChar - ascii('a') + 10
when (@cChar >= ascii('A') and @cChar <= ascii('F')) then @cChar - ascii('A') + 10
end)

select @vNCarryValue=substring(@vNCarryValue,2,len(@vNCarryValue)-1)
-- ,@iLen=len(@vNCarryValue)
-- ,@iPos=@iLen-charindex('1',@vNCarryValue,0)
-- ,@vNCarryValue=right(@vNCarryValue,len(@vNCarryValue)-
-- charindex('1',@vNCarryValue))
-- ,@iValue=@iValue+power(16,@iPos)
-- ,@iCount = @iCount-1
end
else
return 0;
end
return @iValue
END
taoxianxue 2006-04-27
  • 打赏
  • 举报
回复
在哪里加?
tianhxk 2006-04-27
  • 打赏
  • 举报
回复
忘记加10了
taoxianxue 2006-04-27
  • 打赏
  • 举报
回复
首先感谢你回答我的问题

我试用了 但是结果还是不对

468DB371对应的结果应该为18137.72
我头都搞晕了,麻烦各位帮忙再看看
tianhxk 2006-04-27
  • 打赏
  • 举报
回复
charindex('1',@vNCarryValue) 这个是 找字符‘1’在字符串中的位置
比如说 @vNCarryValue = '345614' 那么charindex('1',@vNCarryValue)返回 5

感觉你这里用的不对,每次@pos = 0,这样每次加1,@iCount = 8,所以为 8
加载更多回复(3)

22,209

社区成员

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

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