0

最小の小数値を返す関数を作成しようとしています。サンプルコードはこちら:

create or replace function fraction_sh(x number) return varchar2
is
    fra1 number;
    pwr number;
    intprt number;
    v4 number;
    numer number;
    denom number;
    gcdval number;
    frac varchar2(50);
    begin
       if x <> 0 then  
           fra1 := mod(x,1);
           pwr := length(mod(x,1))-1;
           intprt := trunc(x);
           numer :=mod(x,1)*power(10,length(mod(x,1))-1);
           denom :=power(10,length(mod(x,1))-1);
           gcdval := gcdnew(power(10,length(mod(x,1))-1),mod(x,1)*power(10,length(mod(x,1))-1));
               if intprt = 0 then 
                       frac := to_char(trunc(numer/gcdval))||'/'||to_char(trunc(denom/gcdval));
                DBMS_OUTPUT.put_line(1||' '||denom||' '||gcdval||' '||numer);
              else
                    frac := (intprt*to_char(trunc(denom/gcdval)))+to_char(trunc(numer/gcdval))||'/'||to_char(trunc(denom/gcdval));
                   DBMS_OUTPUT.put_line(2||' '||denom||' '||gcdval||' '||numer);
              end if;
        end if;
     return frac;
end;


create or replace function gcdnew (a number, b number, p_precision number default null, orig_larger_num number default null) return number is
v_orig_larger_num number := greatest(nvl(orig_larger_num,-1),a,b);
v_precision_level number := p_precision;
begin
  if a is null or b is null or (a = 0 and b = 0) then return 1; end if;

  if p_precision is null or p_precision <= 0 then
      v_precision_level := 4; 
  end if;

  if b is null or b = 0 or (b/v_orig_larger_num <= power(10,-1*v_precision_level) and greatest(a,b) <> v_orig_larger_num) then
      return a;
  else
      return (gcdnew(b,mod(a,b),v_precision_level,v_orig_larger_num));
  end if;

終わり;

ほとんどの場合は機能しますが、2/11 を渡そうとすると 2/10 が返されます。

どんな助けでも感謝します。

4

2 に答える 2

0

次のように使用できます。

create or replace function fraction_sh(dividing number,divided number) return varchar2
is 
dividing2 number;
divided2 number;
frac varchar2(100 char); 
temp number;
loop_value boolean;
    begin
     loop_value:=true;
     dividing2:=dividing;
     divided2 :=divided;
       if dividing <> 0 then  
           while loop_value
           loop
           if gcd(dividing2,divided2)<> 1 then
           temp:=gcd(dividing2,divided2);
            dividing2:=dividing2/temp;
            divided2 :=divided2/temp;
            frac:=dividing2||'/'||divided2; 
            else
            loop_value:=false;
            frac:=dividing2||'/'||divided2; 
           end if;          
           end loop;
        else
        frac:='0';
        end if;
     return frac;
end;

gcd 関数:

create or replace function gcd(a number, b number)
  return number is
  begin
     if b = 0 then
        return a;
     else
        return gcd(b,mod(a,b));
     end if;
  end;
于 2018-02-19T12:28:31.520 に答える