JIS, ISO 式四捨五入

なんでも掲示板? の中間さんの投稿記事参照。

桁数の多いデータはしばしば丸め処理 (rounding) される.よく知られたものに, 切り下げ,切り上げ,そして四捨五入がある.四捨五入は切り上げ,切り下げが 相半ばし,長い目で見ると公平であるといわれるが,実際は,少しだけ大きめに 丸める傾向があることは,次の表から分かる.

元の数3.03.13.23.33.43.53.63.73.83.9
四捨五入後3333344444
0.0-0.1-0.2-0.3-0.40.50.40.30.20.1

JIS(日本工業規格)や,ISO(国際標準化機構)では,任意の桁位置における丸め処理法を次のように定めている(JIS Z 8401方式およびISO 3110 方式). この方式は10進法だけでなく,2進法等にも適用される.R の四捨五入関数 round は IEEE 754 方式 (IEEE 規格は計算機における数値処理の基本を定める)に 基づき、 これは JIS, ISO 方式と一致 (簡単にいえば誤差が最小になるように丸めるということ) するが、小学校で習った四捨五入とは微妙に食い違う(つまり五入ばかりでなく五捨もあり得る)ので注意が必要である。

  • (1) 一番近い丸め結果候補が1つだけなら,その数に丸める,
  • (2) 一番近い丸め結果候補が2つある場合は,末尾が偶数のものに丸める,
  • (3) 丸め処理は1段階で行なわなければならない.

例えば小数点以下第1桁に丸めるなら次のようになる.規則 (2) が適用される場合は 通常の四捨五入とは異なる結果になる場合がある.

丸める数12.22312.25112.2512.35
丸め結果12.212.312.212.4
適用規則(1)(1)(2)(2)

規則(3)は,例えば 12.345 は直に12.3と丸めるべきであって、まず12.35とし、 それから12.4としてはならないことを主張している.この規則は,丸めによる 誤差が最小になる利点がある.

> round(122.5)  # 五捨!
[1] 122
> round(122.51) # 五入
[1] 123
> round(123.5) # 五入
[1] 124
> round(122.501) # 五入
[1] 123

計算機ソフトでは,伝統的に通常の四捨五入方式を採用してきた.市販の電卓や パソコンソフトの丸め処理法は,必ずしもJIS,ISO方式になっていないことも多く, チェックが必要であるといわれてる.(今入った情報では、Excel の丸め関数は、小学生方式、一方 VBA は IEEE 方式だそうです。)

とはいえ、実際は気にするほどの差ではない (なにかおかしいかな?)

> test1 <- function () { 
      x <- floor(100*runif(10000000))/10
      y <- round(x)   # JIS, ISO, IEEE 式四捨五入
     mean(abs(x-y))
   }
> test1()
[1] 0.2499519
> test2 <- function () { 
     x <- floor(100*runif(10000000))/10
     y <- oround(x)  # (中間さん作の)世間一般風四捨五入
    mean(abs(x-y))
  }
> test2()
[1] 0.250041

絶対値をとらないで平均すると大きな(?)差 (これで安心)。いずれにしても丸めた方が若干大きくなる傾向に注意。

> test1 <- function () { x <- floor(100*runif(10000000))/10; y <- round(x); mean(x-y)}
> test1()
[1] -5.579e-05
> test2 <- function () { x <- floor(100*runif(10000000))/10; y <- oround(x); mean(x-y)}
> test2()
[1] -0.04997603

中間さんの oround 関数へのコメントに答えるべくシミュレーション。最大一万円の買いものを一千万回したとして、消費税込の値段を、普通の四捨五入と、ISO 式でした場合の食い違い総和は

> test <- function(){
     x <- floor(10000*runif(10000000))
     x <- 1.05*x
     sum(oround(x) -x)}
> test()
[1] 249700.4  # 現状方式では25万円消費者がとられすぎ。
> test <- function(){
     x <- floor(10000*runif(10000000))
     x <- 1.05*x
    sum(round(x) -x)}
> test()
[1] 1515.3     # ISO 式!

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Google
WWW を検索 OKADAJP.ORG を検索
Last-modified: 2015-03-01 (日) 01:15:59 (1718d)