原文http://blog.csdn.net/yzsind/archive/2008/07/02/2604798.aspx 感谢作者
刚在CNOUG看到有人提问如何用PL/SQL 实现小数转分数的问题,下面这段代码是我的实现,主要思路是将输入的整数及小数都分别取出,然后将小数写成以10的n次方的分数,再求其最大公约数,得到简化的分数,最后将整数及分数合并。代码里有一些处理细节,如负数处理,纯整数处理,纯小数处理等等。
create or replace function dftof(iStr number) return varchar2 as
- --小数转分数
- -- (decimal fraction) to fraction
- --设计人:叶正盛
- v_Str varchar(50);
- result varchar(50);
- v_fh varchar(1); --负数符号
- v_zs varchar2(20); --整数
- v_xs varchar2(20); --小数
- v_pos int; --小数点位置
- v_fm integer; --分母
- v_fz integer; --分子
- v_zdgys integer; --最大公约数
- --求最大公约数
- function getZDGYS(iNum1 integer, iNum2 integer) return integer as
- v_ys integer; --余数
- v_num1 integer;
- v_num2 integer;
- begin
- v_num1 := iNum1;
- v_num2 := iNum2;
- v_ys := mod(v_num1, v_num2);
- --辗转相除法
- while v_ys <> 0 loop
- v_num1 := v_num2;
- v_num2 := v_ys;
- v_ys := mod(v_num1, v_num2);
- end loop;
- return v_num2;
- end;
- begin
- v_Str := trim(iStr);
- v_pos := instr(v_Str, '.'); --计算小数点位置
- if v_pos = 0 then
- result := v_Str; --纯整数
- else
- if substr(v_Str, 1, 1) = '-' then
- v_zs := substr(v_Str, 2, v_pos - 2); --整数
- else
- v_zs := substr(v_Str, 1, v_pos - 1); --整数
- end if;
- v_xs := substr(v_Str, v_pos + 1); --小数
- if to_number(nvl(v_zs, '0')) = 0 then
- if substr(v_zs, 1, 1) = '-' then
- v_zs := '-'; --如果整数为-0则显示负号
- else
- v_zs := ''; --如果整数为0则不显示整数
- end if;
- else
- v_zs := v_zs || '+'; --整数部份显示样式
- end if;
- v_fz := to_number(v_xs); --分子
- v_fm := power(10, length(v_xs)); --分母
- v_zdgys := getZDGYS(v_fm, v_fz); --求最大公约数
- result := (v_fz / v_zdgys) || '/' || (v_fm / v_zdgys);
- if substr(v_Str, 1, 1) = '-' then
- result := '-(' || v_zs || result || ')';
- else
- result := v_zs || result;
- end if;
- end if;
- return result;
- end;
- 测试结果
- Connected to Oracle9i Enterprise Edition Release 9.2.0.7.0
- Connected as yzs
- SQL> select dftof(0.4) from dual;
- DFTOF(0.4)
- --------------------------------------------------------------------------------
- 2/5
- SQL> select dftof(3.4) from dual;
- DFTOF(3.4)
- --------------------------------------------------------------------------------
- 3+2/5
- SQL> select dftof(-92.25) from dual;
- DFTOF(-92.25)
- --------------------------------------------------------------------------------
- -(92+1/4)
- SQL> select dftof(-0.375) from dual;
- DFTOF(-0.375)
- --------------------------------------------------------------------------------
- -(3/8)
- SQL> select dftof(-.375) from dual;
- DFTOF(-.375)
- --------------------------------------------------------------------------------
- -(3/8)