页面

2015年7月23日星期四

Oracle PL/SQL方法实现四舍六入五双

/*
                 "四舍六入五双" ---统计实现
名词解释:
  四舍六入五双 规则如下:
  1. 被修约的数字小于5时,该数字舍去;
  2. 被修约的数字大于5时,则进位;
  3. 被修约的数字等于5时,要看5前面的数字,若是奇数则进位,
    若是偶数则将5舍掉,即修约后末尾数字都成为偶数;若5的后
面还有不为“0”的任何数,则此时无论5的前面是奇数还是偶数,均应进位。

举例:
   9.8249=9.82, 9.82671=9.83
   9.8350=9.84, 9.8351 =9.84
   9.8250=9.82, 9.82501=9.83

四舍六入五双 在统计学方面是比四舍五如更为科学的统计方法,特别是做大量数据统计时。



以上内容摘自百度百科。
既然知道了规则,就知道如何实现了。
以下是使用 PL/SQL 实现四舍六入五双写的方法。
该方法返回字符串类型,可以通过 to_number() 方法来显式转换成数字。

*/
create or replace function fnRound(v_num number,i int)   --v_num 需要被修约的数字,保留小数位数。
return varchar2
is
  str1 varchar2(100);     ---用于存放v_num最高位到被修约位的字符串。
  v_num2 number;   ---存放去掉小数点后的str1,转换成的整数。
  v_result varchar2(100);  --结果
 
begin
  str1 := substr(to_char(v_num),1,instr(to_char(v_num),'.')+i+1);
  v_num2 := to_number(replace(str1,'.',''));
 
  /*
    通过mod(v_num2,5) 就可以判断被修约位是否为0或者5(如果被修约位为0,该算法也符合)
完整条件写法为 if (mod(v_num2,5) = 0 mod(v_num2,10)<>0 and v_num = to_number(str1))
而且被修剪的数字与原始数字相等则进行判断:
如果被修约位前一位数字为偶数,则直接舍去。
如果被修约位前一位数字为奇数,则进1.
  */
  if (mod(v_num2,5) = 0 and v_num = to_number(str1)) then
    if mod(trunc(v_num2/10),2)=0 then                        --如果被修约位前一位数字为偶数
      v_result := substr(str1,1,length(str1)-1);            
    else                                                     --如果被修约位前一位数字为奇数
      v_result := to_char(ceil(v_num2/10)/power(10,i));
    end if;
/*
 如果被修约位为5,而且原始数在被修约位后还有数字,则直接进1.
 完整条件写法为 if (mod(v_num2,5) = 0 mod(v_num2,10)<>0 and v_num >to_number(str1))
*/
  elsif(mod(v_num2,5) = 0 and v_num > to_number(str1)) then  
      v_result := to_char(ceil(v_num2/10)/power(10,i));
  else         ---被修约位不是5,则按照四舍六入规则进行
      v_result := to_char(round(v_num,i));
  end if;
  return v_result;
end;

没有评论:

发表评论