zoukankan      html  css  js  c++  java
  • .关于货币大写的探索

    尝试了一下货币的大写的方法,自己从论坛上看到,到自己亲手实践,已经可以实现上述的需求,中间思路和算法也更换了几次写出来程序的雏形,有待优化的地方,但是作为自己的思路,把自己的算法记录下来,待以后进一步改进。

     
     
         1、自己的算法
     
     
    create or replace function lcw_get_money(money in number) return varchar2 is
      max_num   number := 0;
      v_num     number := 0;
      v_char    varchar2(200);
      retcode number:=0;
      errbuf varchar2(200);
      Result varchar2(200);
      v_error exception;
    begin
      if length(money)>9 then
       raise v_error;
      end if;
      max_num:=length(money);
      v_num := max_num;
      loop
         v_char:=substr(money, v_num, 1); 
          case
          when v_num = max_num and substr(money, v_num, 1)<>0 then
            result := v_char || '元整' || result;
          when v_num = max_num and substr(money, v_num, 1)=0 then
            result := '元整' || result;
          when (v_num = max_num-1 or v_num = max_num-5)  and substr(money, v_num, 1)<>0 then
            result := v_char || '拾' || result;
           when (v_num = max_num-1 or v_num = max_num-5) and substr(money, v_num, 1)=0 then
            result := v_char|| result;
          when (v_num = max_num-2 or  v_num = max_num-6)  and substr(money, v_num, 1)<>0 then
            result := v_char || '佰' || result;
          when (v_num = max_num-2 or  v_num = max_num-6)  and substr(money, v_num, 1)=0 then
            result := v_char|| result;
            when (v_num = max_num-3 or  v_num = max_num-7) and substr(money, v_num, 1)<>0 then
            result := v_char || '仟' || result;
           when v_num = max_num-3 and substr(money, v_num, 1)=0 then
            result := v_char || result;
           when v_num = max_num-4 and substr(money, v_num, 1)<>0 then
            result := v_char || '万' || result;
            when v_num = max_num-4 and substr(money, v_num, 1)=0 then
            result := '万'|| result;
            when v_num = max_num-8 and substr(money, v_num, 1)<>0 then
            result := v_char || '亿' || result;
            when v_num = max_num-8 and substr(money, v_num, 1)=0 then
            result := '亿'|| result;
            else  retcode:=2;
        end case;
          v_num := v_num - 1;
        exit when v_num=0;
      end loop;
      select translate(regexp_replace(regexp_replace(result,'0+(元|万)','\1'),'0+','0'),'0123456789','零壹贰叁肆伍陆柒捌玖')
        into Result
        from dual;
        return(Result);
      exception
        when v_error then
         raise_application_error(1,'超出了计算范围');
      when others then
            retcode := 2 ;
            errbuf := sqlcode||': '||sqlerrm ;
            raise_application_error(2,errbuf);
    end lcw_get_money;
     
    PS: 想办法完美解决了恼人的0的问题,但是程序可读性随强,但是还没有融入巧妙的算法,属于自己认识水平有限的问题,还要继续努力。
     
      2、同事的解法
     
    create or replace function xf_get_money(money in VARCHAR2)
       return varchar2 is
         c_money  VARCHAR2(12);
         b_string VARCHAR2(80);
         m_string VARCHAR2(60) := '分角圆拾佰仟万拾佰仟亿';
         n_string VARCHAR2(40) := '壹贰叁肆伍陆柒捌玖';
         n         CHAR;
         len       NUMBER(10);
         i         NUMBER(10);
         tmp       NUMBER(12);
         is_zj     BOOLEAN;
         z_count   NUMBER(10);
         l_money   NUMBER;
         l_money1  NUMBER;
         l_sign    VARCHAR2(10);
       BEGIN
         l_money1 :=to_number(money);
         l_money :=abs(money);
         IF l_money1 < 0 THEN
           l_sign := '负' ;
         ELSE
           l_sign := '';
         END IF;
         tmp     := round(l_money, 2) * 100;
         c_money := rtrim(ltrim(to_char(tmp, '999999999999')));
         len     := length(c_money);
         is_zj := TRUE;
         z_count := 0;
         i       := 0;
         WHILE i < len LOOP
           i := i + 1;
           n := substr(c_money, i, 1);
           IF n = '0' THEN
             IF len - i = 6 OR len - i = 2 OR len = i THEN
               IF is_zj THEN
                 b_string := substr(b_string, 1, length(b_string) - 1);
                 is_zj   := FALSE;
               END IF;
               IF len - i = 6 THEN
                 b_string := b_string || '万';
               END IF;
               IF len - i = 2 THEN
                 b_string := b_string || '圆';
               END IF;
               IF len = i THEN
                 b_string := b_string || '整';
               END IF;
               z_count := 0;
             ELSE
               IF z_count = 0 THEN
                 b_string := b_string || '零';
                 is_zj   := TRUE;
               END IF;
               z_count := z_count + 1;
             END IF;
           ELSE
             b_string := b_string || substr(n_string, to_number(n), 1) ||
                         substr(m_string, len - i + 1, 1);
             z_count  := 0;
             is_zj  := FALSE;
           END IF;
         END LOOP;
         b_string := l_sign || b_string ;
         RETURN b_string;
    EXCEPTION
        WHEN OTHERS THEN
           RETURN(SQLERRM);
    END;
     
    PS:程序写的比较简洁,巧妙的使用了算法,减低了编程的劳动强度,但是对其对0的处理方法,依然表示还有疑惑,留待以后继续考证研究。

       经过中午的推敲,咱明白了同事的做法的技巧思路在于考虑加0策略,而我自己思路在于减0,由于需要加0的情况较少,所以此题更适合采用加0算法。于是咱就用新学的raise_application_error 的函数进行了,从右向左的扫描,成功的完成如上的需求:

       3、改良过的程序

    create or replace function lcw_convert_money(money in number) return varchar2 is
      money_1 number;
      max_num   number := 0;
      m_char varchar2(18):='壹贰叁肆伍陆柒捌玖';
      n_char varchar2(22):='分角圆拾佰仟万拾佰仟亿';
      v_num     number := 0;
      v_char    varchar2(200);
      v_judge number;
      Result varchar2(200);
    begin
      money_1:=money*100;
      max_num:=length(money_1);
      v_num := max_num;
      case when max_num>11 then
        raise_application_error(-20988,'超出了函数的运算范围!');
        else
        for i in 1..v_num loop
         v_char:=substr(money_1, v_num,1);
         case when v_char=0 then
              case when v_num=max_num or max_num-v_num=2 or max_num-v_num=6 then
                   case when v_num=max_num then
                     result:= '整';
                        when max_num-v_num=2 then
                     result:='圆'||result;
                        when max_num-v_num=6 then
                     result:='万'||result;
                   end case;
               else case when v_judge=0 then
                     result:='零'||result;
                     v_judge:=1;
                    else null;
                     end case;
               end case;
            else result:=substr(m_char,v_char,1)||substr(n_char,i,1)||result;
                 v_judge:=0; 
         end case;
         v_num := v_num - 1;
        exit when v_num=0;
      end loop;
        return(Result);
        end case;
      exception
      when others then
         return(sqlcode||':'||sqlerrm);
    end lcw_convert_money;

    经过测试可以顺利完成如上需求,并且中间经过确认case else逻辑判断是并行的,比if..else执行效率要高,也是对咱细节的优化吧。

  • 相关阅读:
    ActionBar Fragment的一个sample activity; 及获取runningAppProcess及跳转
    优化后台推送的service,减少被杀死的几率
    64位win7安装ubunto最新14.04的过程,及出现的问题的解决
    一次非线上iowait高的情况的检查
    一个愚蠢的python逻辑语法错误
    Bellman-Ford算法解决单源最短路问题
    Floyd算法解决多源最短路径问题
    最短路问题Dijkstra算法
    最小生成树之Kruskal算法
    最优二叉搜索树
  • 原文地址:https://www.cnblogs.com/liuweicong39/p/2586534.html
Copyright © 2011-2022 走看看