基本的な考え方
ある数値の桁数を取得するには常用対数を用います。
FLOOR(LOG(10, n))
は次のとおり0以外の数値が最初に出現する桁を表します。
SQL> WITH DATA AS ( 2 SELECT 1234 N FROM DUAL 3 UNION ALL SELECT 234 N FROM DUAL 4 UNION ALL SELECT 34 N FROM DUAL 5 UNION ALL SELECT 4 N FROM DUAL 6 --UNION ALL SELECT 0 N FROM DUAL 7 UNION ALL SELECT 0.123 N FROM DUAL 8 UNION ALL SELECT 0.0234 N FROM DUAL 9 UNION ALL SELECT 0.00345 N FROM DUAL 10 ) 11 SELECT N, FLOOR(LOG(10, N)) FROM DATA; N FLOOR(LOG(10,N)) ---------- ---------------- 1234 3 234 2 34 1 4 0 .123 -1 .0234 -2 .00345 -3
注: LOG(10, 0) は次のエラーを発生させます。: ORA-01428: 引数'0'が有効範囲外です
したがって、ROUND(n, - FLOOR(LOG(10, n)))
で最初の1桁で丸めを行った値を取得することができます。
SQL> WITH DATA AS ( 2 SELECT 1234 N FROM DUAL 3 UNION ALL SELECT 234 N FROM DUAL 4 UNION ALL SELECT 34 N FROM DUAL 5 UNION ALL SELECT 4 N FROM DUAL 6 --UNION ALL SELECT 0 N FROM DUAL 7 UNION ALL SELECT 0.123 N FROM DUAL 8 UNION ALL SELECT 0.0234 N FROM DUAL 9 UNION ALL SELECT 0.00345 N FROM DUAL 10 ) 11 SELECT N, ROUND(n, - FLOOR(LOG(10, N))) FROM DATA; N ROUND(N,-FLOOR(LOG(10,N))) ---------- -------------------------- 1234 1000 234 200 34 30 4 4 .123 .1 .0234 .02 .00345 .003
最初の d 桁で丸めるには、ROUND(n, d - 1- FLOOR(LOG(10, n)))
とします。
関数
以上を関数にまとめると次のようになります。
CREATE OR REPLACE FUNCTION SIGNIFICANT_FIGURES( n NUMBER, d NUMBER ) RETURN NUMBER IS BEGIN IF n = 0 THEN RETURN 0; ELSE ROUND(n, d - 1 - FLOOR(LOG(10, n))); END IF; END;
偶数丸めを行うには、ROUND
関数の代わりに ROUND_HALF_EVEN
関数を使います。
注: Oracle Database 18c からROUND_TIES_TO_EVEN
関数が使えます。