此 Stored Procedure 可將輸入的十進制數字轉換為 IEEE 754 標準二進制浮點格式 (32 bits) 輸出。
IEEE 754 共分為 S (Sign)、E (Exponent)、M (Mantisa) 三個部分 -
計算方式: 以 -60.25 為例
1) -60.25 為負數,將 S 設定為 1 (若為正數則設定為 0)。
2) 將 60.25 轉換為二進制浮點數 111100.01
3) 將此二進制浮點數正規劃 1.1110001 * 2^5
4) 將 5 (2 的乘方) 加上 127 後,轉換為二進制 10000100,存放於 E。
5) 將 1.1110001 去掉最前面的 "1." 後,存放於 M (共 32 bits,不足補 0);得到 11100010000000000000000 。
6) 最後得到 1 10000100 11100010000000000000000
程式碼
if object_id ('usp_IEEE754_Generate') is not null
drop proc usp_IEEE754_Generate
go
create proc usp_IEEE754_Generate @prm_num float,
@rtn_IEEE_754_string varchar(32) output,
@rtn_IEEE_754_binary_codes binary(32) output
/*----------------------------------------------------------------------------------+
| Author: Wei-jie Yang |
| Date: 2012/05/10 |
| All Rights Reserved |
| |
| [Description] |
| This stored procedure is used to convert decimal floating number into binary |
| floating number according to IEEE 754 (Standard for Binary Floating-Point |
| Arithmetic). |
| |
| [Parameters] |
| (1).INPUT Parameter |
| - @prm_num: The number is going to be converted. |
| (2).OUTPUT Parameter |
| - @rtn_IEEE_754_string: Converted number stored in varchar data type |
| - @rtn_IEEE_754_codes : Converted number stored in binary data type |
| |
| [Usage] |
| declare @return_1 varchar(32), @return_2 binary(32) |
| exec usp_IEEE754_Generate -0.75, @return_1 output, @return_2 output |
| select @return_1 as Varchar_Mode |
| select @return_2 as Binary_Mode |
+----------------------------------------------------------------------------------*/
as
declare @dot_position int,
@exp_part_0_1 varchar(8),
@fraction_part float,
@fraction_part_0_1 varchar(23),
@i int,
@integer_fraction_0_1 varchar(100),
@integer_part int,
@integer_part_0_1 varchar(23),
@j int,
@k int,
@leading_one_position int,
@sign char(1), -- 0: Zero, Positive Number 1: Negative Number
@single_digit char(1),
@temp_exp int,
@temp_fraction float,
@temp_integer int
declare @integer_result table (
i_sn int,
i_digit char(1)
)
declare @exp_result table (
e_sn int,
e_digit char(1)
)
set nocount on
-- Initialization ---------------------------------------------------
if @prm_num = 0
goto Zero_Handler
if @prm_num > 0
begin
select @sign = '0'
end
else
begin
select @sign = '1'
select @prm_num = @prm_num * -1
end
select @integer_part = @prm_num / 1
select @fraction_part = @prm_num - @integer_part
---------------------------------------------------------------------
-- Integer Part -----------------------------------------------------
select @temp_integer = @integer_part
select @i = 1
while @temp_integer > 1
begin
select @single_digit = @temp_integer % 2
select @temp_integer = @temp_integer / 2
insert into @integer_result values(@i, @single_digit)
select @i = @i + 1
end
insert into @integer_result values(@i, @temp_integer)
select @integer_part_0_1 = ''
while @i > 0
begin
select @single_digit = i_digit
from @integer_result
where i_sn = @i
select @integer_part_0_1 = @integer_part_0_1 + @single_digit
select @i = @i - 1
end
---------------------------------------------------------------------
-- Fraction Part ----------------------------------------------------
select @temp_fraction = @fraction_part
select @j = 1
select @fraction_part_0_1 = ''
if @temp_fraction > 0
begin
while @temp_fraction > 0
begin
select @temp_fraction = @temp_fraction * 2
if @temp_fraction >= 1
begin
select @single_digit = 1
select @temp_fraction = @temp_fraction - 1
end
else
begin
select @single_digit = 0
end
select @fraction_part_0_1 = @fraction_part_0_1 + @single_digit
end
end
else
begin
select @fraction_part_0_1 = '0'
end
---------------------------------------------------------------------
select @integer_fraction_0_1 = @integer_part_0_1 + '.' + @fraction_part_0_1
select @leading_one_position = charindex('1', @integer_fraction_0_1)
select @dot_position = charindex('.', @integer_fraction_0_1)
if @dot_position < @leading_one_position
select @temp_exp = @dot_position - @leading_one_position + 127
else
select @temp_exp = @dot_position - @leading_one_position - 1 + 127
select @integer_fraction_0_1 = replace(@integer_fraction_0_1, '.', '')
select @integer_fraction_0_1 = replace(ltrim(replace(@integer_fraction_0_1, '0', ' ')), ' ', '0') -- remove leading zeros
select @integer_fraction_0_1 = substring(@integer_fraction_0_1, 2, len(@integer_fraction_0_1)) -- remove the first '1'
-- Exponential Part -------------------------------------------------
select @k = 1
while @temp_exp > 1
begin
select @single_digit = @temp_exp % 2
select @temp_exp = @temp_exp / 2
insert into @exp_result values(@k, @single_digit)
select @k = @k + 1
end
insert into @exp_result values(@k, '1')
select @exp_part_0_1 = ''
while @k > 0
begin
select @single_digit = e_digit
from @exp_result
where e_sn = @k
select @exp_part_0_1 = @exp_part_0_1 + @single_digit
select @k = @k - 1
end
select @exp_part_0_1 = right('00000000' + @exp_part_0_1, 8)
---------------------------------------------------------------------
-- IEEE 754 Format --------------------------------------------------
select @rtn_IEEE_754_string = left(convert(varchar(32), @sign + @exp_part_0_1 + @integer_fraction_0_1, 2) + '00000000000000000000000000000000', 32)
select @rtn_IEEE_754_binary_codes = convert(binary(32), @rtn_IEEE_754_string, 2)
---------------------------------------------------------------------
set nocount off
return
Zero_Handler:
select @rtn_IEEE_754_string = '00000000000000000000000000000000'
select @rtn_IEEE_754_binary_codes = convert(varbinary(64), @rtn_IEEE_754_string, 2)
set nocount off
return